unittest - Prüfe auf Typ

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.
Benutzeravatar
TheGrudge
User
Beiträge: 89
Registriert: Donnerstag 4. Mai 2006, 18:39

unittest - Prüfe auf Typ

Beitragvon TheGrudge » Sonntag 12. November 2006, 09:34

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")
Benutzeravatar
TheGrudge
User
Beiträge: 89
Registriert: Donnerstag 4. Mai 2006, 18:39

Beitragvon TheGrudge » Sonntag 12. November 2006, 09:35

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")
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Re: unittest - Prüfe auf Typ

Beitragvon gerold » Sonntag 12. November 2006, 11:34

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
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
TheGrudge
User
Beiträge: 89
Registriert: Donnerstag 4. Mai 2006, 18:39

Beitragvon TheGrudge » Sonntag 12. November 2006, 12:44

aber dann besteht doch auch ein Iterator den Test, oder etwa nicht? Es sollen wirklich nur Generatoren erlaubt sein.
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Sonntag 12. November 2006, 12:56

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'
My god, it's full of CARs! | Leonidasvoice vs Modvoice
BlackJack

Beitragvon BlackJack » Sonntag 12. November 2006, 12:57

TheGrudge hat geschrieben:aber dann besteht doch auch ein Iterator den Test, oder etwa nicht? Es sollen wirklich nur Generatoren erlaubt sein.


Warum?
BlackJack

Beitragvon BlackJack » Sonntag 12. November 2006, 13:01

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.
Benutzeravatar
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Beitragvon mitsuhiko » Sonntag 12. November 2006, 13:34

Code: Alles auswählen

>>> from types import GeneratorType
>>> def foo():
...  yield "blub"
...
>>> isinstance(foo(), GeneratorType)
True


Wenns wirklich nur ein Generator sein darf.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
TheGrudge
User
Beiträge: 89
Registriert: Donnerstag 4. Mai 2006, 18:39

Beitragvon TheGrudge » Sonntag 12. November 2006, 14:14

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!
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Montag 13. November 2006, 11:20

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?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Beitragvon birkenfeld » Montag 13. November 2006, 11:34

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.
BlackJack

Beitragvon BlackJack » Montag 13. November 2006, 11:34

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
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Montag 13. November 2006, 14:16

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.
My god, it's full of CARs! | Leonidasvoice vs Modvoice

Wer ist online?

Mitglieder in diesem Forum: pillmuncher