Seite 1 von 1

unittest - Prüfe auf Typ

Verfasst: Sonntag 12. November 2006, 09:34
von TheGrudge
Hallo,

ich habe mir überlegt wie ich eine Funktion daraufhin testen kann, ob sie einen Generator zurückliefert.
Nun kam ich auf folgenden Code und wollte einfach nur mal fragen, ob das die beste Methode ist so etwas zu testen oder ob es irgendeine andere Möglichkeit gibt.

Code: Alles auswählen

def test_return_generator(self):
       """func1 should return a generator object"""
        t = type(func1("test"))
        self.assertEqual(t.__name__, "generator")

Verfasst: Sonntag 12. November 2006, 09:35
von TheGrudge
hmm also ich weiss nicht wie es bei euch aussieht, aber ich sehe keine Unterstriche... sollte also im Code heissen:
self.assertEqual(t.__name__, "generator")

Re: unittest - Prüfe auf Typ

Verfasst: Sonntag 12. November 2006, 11:34
von gerold
TheGrudge hat geschrieben:ich habe mir überlegt wie ich eine Funktion daraufhin testen kann, ob sie einen Generator zurückliefert.
Hallo TheGrudge!

Ich würde einfach nur prüfen, ob das Objekt das Attribut ``next`` besitzt:

Code: Alles auswählen

>>> def x():
...     for i in range(2):
...         yield i
...     
>>> xx = x()
>>> print hasattr(xx, "next")
True
>>>

Code: Alles auswählen

def is_generator(generator_object):
    return hasattr(generator_object, "next")

x = ( item for item in range(2) )

print is_generator(x)
mfg
Gerold
:-)

Verfasst: Sonntag 12. November 2006, 12:44
von TheGrudge
aber dann besteht doch auch ein Iterator den Test, oder etwa nicht? Es sollen wirklich nur Generatoren erlaubt sein.

Verfasst: Sonntag 12. November 2006, 12:56
von Leonidas
TheGrudge hat geschrieben:aber dann besteht doch auch ein Iterator den Test, oder etwa nicht? Es sollen wirklich nur Generatoren erlaubt sein.
Iteratoren implementieren __iter__(), nicht next():

Code: Alles auswählen

In [44]: iter = xrange(5)
In [45]: iter.next()
---------------------------------------------------------------------------
<type 'exceptions.AttributeError'>        Traceback (most recent call last)

/home/leonidas/<ipython console> in <module>()

<type 'exceptions.AttributeError'>: 'xrange' object has no attribute 'next'

Verfasst: Sonntag 12. November 2006, 12:57
von BlackJack
TheGrudge hat geschrieben:aber dann besteht doch auch ein Iterator den Test, oder etwa nicht? Es sollen wirklich nur Generatoren erlaubt sein.
Warum?

Verfasst: Sonntag 12. November 2006, 13:01
von BlackJack
Leonidas hat geschrieben:
TheGrudge hat geschrieben:aber dann besteht doch auch ein Iterator den Test, oder etwa nicht? Es sollen wirklich nur Generatoren erlaubt sein.
Iteratoren implementieren __iter__(), nicht next():
Iteratoren implementieren `__iter__()`, das per Definition `self` zurückgeben sollte, und `next()`.

`xrange()` ist kein Iterator, sondern ein `iterable` oder etwas konkreter: es implementiert das `sequence`-Protokoll.

Verfasst: Sonntag 12. November 2006, 13:34
von mitsuhiko

Code: Alles auswählen

>>> from types import GeneratorType
>>> def foo():
...  yield "blub"
... 
>>> isinstance(foo(), GeneratorType)
True
Wenns wirklich nur ein Generator sein darf.

Verfasst: Sonntag 12. November 2006, 14:14
von TheGrudge
blackbird hat geschrieben:

Code: Alles auswählen

>>> from types import GeneratorType
>>> def foo():
...  yield "blub"
... 
>>> isinstance(foo(), GeneratorType)
True
Wenns wirklich nur ein Generator sein darf.
Danke!

Verfasst: Montag 13. November 2006, 11:20
von Leonidas
BlackJack hat geschrieben:`xrange()` ist kein Iterator, sondern ein `iterable` oder etwas konkreter: es implementiert das `sequence`-Protokoll.
Ok, danke für die Klarstellung. Hast du auch noch irgendwelche weiteren Quellen, wo man sich über Datails informieren könnte?

Verfasst: Montag 13. November 2006, 11:34
von birkenfeld
http://svn.python.org/projects/python/t ... geobject.c

Man sieht: ein xrange-objekt implementiert sowohl das traditionelle sequence-Protokoll, stellt aber auch __iter__ zur Verfügung, was ein "rangeiterator"-Objekt erstellt, das zum Iterieren verwendet wird.

Verfasst: Montag 13. November 2006, 11:34
von BlackJack
Leonidas hat geschrieben:
BlackJack hat geschrieben:`xrange()` ist kein Iterator, sondern ein `iterable` oder etwas konkreter: es implementiert das `sequence`-Protokoll.
Ok, danke für die Klarstellung. Hast du auch noch irgendwelche weiteren Quellen, wo man sich über Datails informieren könnte?
Du meinst ausser *den* Quellen, sprich Python-Quelltext? ;-)

Hauptsächlich Beobachtung, es verhält sich wie eine Sequenz und nicht wie ein Iterator:

Code: Alles auswählen

In [9]: a = xrange(0, 10, 2)

In [10]: a.
a.__class__         a.__init__          a.__repr__
a.__delattr__       a.__iter__          a.__reversed__
a.__doc__           a.__len__           a.__setattr__
a.__getattribute__  a.__new__           a.__str__
a.__getitem__       a.__reduce__
a.__hash__          a.__reduce_ex__

In [10]: len(a)
Out[10]: 5

In [11]: a[0]
Out[11]: 0

In [12]: a[2]
Out[12]: 4

In [13]: a[100]
---------------------------------------------------------------------------
exceptions.IndexError         Traceback (most recent call last)

/home/marc/<ipython console>

IndexError: xrange object index out of range

Verfasst: Montag 13. November 2006, 14:16
von Leonidas
BlackJack hat geschrieben:Du meinst ausser *den* Quellen, sprich Python-Quelltext? ;-)
Exakt :) Wobei das von birkenfeld gepostete rangeobject.c erstaunlich übersichtlich ist.

Aber danke fürs Codeschnippsel, hilft mir auch schon mal weiter.