Seite 1 von 1

Generator hinter einem Callable verstecken?

Verfasst: Freitag 20. Januar 2012, 20:45
von Hyperion
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

Re: Generator hinter einem Callable verstecken?

Verfasst: Freitag 20. Januar 2012, 20:54
von Dav1d
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'

Re: Generator hinter einem Callable verstecken?

Verfasst: Freitag 20. Januar 2012, 21:34
von bords0
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.

Re: Generator hinter einem Callable verstecken?

Verfasst: Freitag 20. Januar 2012, 21:34
von 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'

Re: Generator hinter einem Callable verstecken?

Verfasst: Freitag 20. Januar 2012, 21:38
von lunar
Wozu die Klasse? Eine partielle Funktion "f = functools.partial(next, foo())" tut es doch auch...

Re: Generator hinter einem Callable verstecken?

Verfasst: Freitag 20. Januar 2012, 21:40
von Hyperion
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.

Re: Generator hinter einem Callable verstecken?

Verfasst: Samstag 21. Januar 2012, 10:57
von Dav1d
:evil:

Re: Generator hinter einem Callable verstecken?

Verfasst: Samstag 21. Januar 2012, 18:03
von Hyperion
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.