Generator hinter einem Callable verstecken?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hallo zusammen,

ich steh grad auf dem Schlauch und komme einfach nicht drauf. Ich suche eine Möglichkeit, wie ich ein `callable` definieren kann, welches beim Aufruf eine intern definierte Datenstruktur iteriert, so dass bei jedem Aufruf des `callables` der nächste Wert zurückgegeben wird, solange bis das Iterable am Ende angelangt ist.

Zur Verdeutlichung mal als Beispiel:

Code: Alles auswählen

def func():
    data = ["Hello", "World"]
    # magic

func()
-> Hello

func()
-> World
Beim ersten Aufruf von `func` wird das erste Element zurückgegeben, beim zweiten Aufruf das zweite, usw.

Ich kann das natürlich so angehen:

Code: Alles auswählen

In [153]: def foo():
   .....:     for item in ("Hello", "World"):
   .....:         yield item
   .....:         
   .....:         

In [154]: def call(iterator):
   .....:     return iterator.next()
   .....: 

In [155]: iobj = foo()

In [156]: call(iobj)
Out[156]: 'Hello'

In [157]: call(iobj)
Out[157]: 'World'
Aber so muss ich mir ja "global" `iobj` merken - geht das nicht irgend wie innerhalb einer Funktion?

Das kann doch nicht so schwer sein... :K
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ich würde das mit einer Klasse lösen:

Code: Alles auswählen

In [27]: class IW(object):
   ....:     def __init__(self, iterator):
   ....:         self.iterator = iterator() if callable(iterator) else iterator
   ....:     def __call__(self):
   ....:         return next(self.iterator)
   ....: 

In [28]: def foo():
   ....:     for item in ("Hello", "World"):
   ....:         yield item
   ....:         

In [29]: i = IW(foo)

In [30]: i()
Out[30]: 'Hello'

In [31]: i()
Out[31]: 'World'
the more they change the more they stay the same
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

Funktionen kann man z.B. einen Zustand mittels default-Argumenten geben:

Code: Alles auswählen

def f(a=iter(["Hello", "World"])):
...     return next(a)
... 
"Richtig" wäre es aber, ein Objekt zu verwenden.
BlackJack

@Dav1d: Die Klasse ist IMHO überflüssig:

Code: Alles auswählen

In [2]: f = foo().next

In [3]: f()
Out[3]: 'Hello'

In [4]: f()
Out[4]: 'World'
lunar

Wozu die Klasse? Eine partielle Funktion "f = functools.partial(next, foo())" tut es doch auch...
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Danke für die Vorschläge - BlackJacks Idee ist ja die offensichtliche... wusste ich doch, dass das ganz einfach gehen muss :-D Den werde ich verwenden.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

:evil:
the more they change the more they stay the same
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dav1d hat geschrieben::evil:
Ach komm! ;-)

So, hier kurz wozu ich das brauchte. Ich wollte eine kleine AI für dieses sonderbare Spiel anbieten. Diese zieht einfach nach einer festen Vorgabe. Damit der Aufruf passend zum "human player" bleibt, suchte ich eine Lösung für dieses Problem.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten