作为记忆机制的一部分,我有一个生成器,我tee
,我需要用isinstnace
检查它的类型。
>>> gen = (i for i in range(5))
>>> one, two = itertools.tee(gen, 2)
然后
>>> type(one), type(two)
(itertools.tee, itertools.tee)
正如所料,但
>>> isinstance(one, itertools.tee)
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
那么tee
的实例是什么?
答案 0 :(得分:4)
itertools.tee
是一个函数,而不是一个类(请参阅type(itertools.tee)
)。它返回tee
类的实例(有点令人困惑)的对象,但该类在itertools
命名空间中不可用。我只是使用type()
从一个实例中获取它。如果您没有方便的实例,请创建一个。这似乎是获取tee
类型的最小代码量:
TeeType = type(itertools.tee(())[0])
看来tee
始终为每次调用使用相同的类。
答案 1 :(得分:4)
tee
是一个返回Python使用的内部实现类型的函数。一般来说,它应该是tee
或任何其他iterator
/ generator
类型。
那就是说,如果你真的需要输入这样的测试,你可以这样做,你只需要像检查类型那样导出tee
实例的“真实”类型,方法是使用type
。例如,要将tee
实例的类型存储在名为Tee
的变量中,您需执行以下操作:
Tee = type(itertools.tee(())[0])
调用tee
来获取实例,然后使用type
获取他们的类。
这是记录的唯一可移植方式;实际类型涉及(正在实现内部)从发布到发布的变化;在Python 3.5中,您可以将原始类型作为itertools._tee
访问,但显然在您的版本中,它不会像那样暴露。
答案 2 :(得分:2)
isinstance用于检查是否有东西说它是鸭子,无论它是否是鸭子。
要回答您的直接问题,isinstance.tee是一种方法,而不是类,或类型的类型或元组:
>>> type(itertools.tee)
<class 'builtin_function_or_method'>
(事实上,在我的python版本中,类已经从选项列表中删除了)。 Python是一种“鸭型”语言。基本上,为了让'isinstance'说某事是另一件事的一个实例,它必须以某种方式从它继承。
示例:
>>> type(str)
<class 'type'>
>>> s = "foo"
>>> isinstance(s,str)
True
>>> class myString(str): #myString inherits from str (a type)
... def __init__(self,s):
... super().__init__()
...
>>> s = myString("foo")
>>> s
'foo'
>>> isinstance(s,str)
True
首先,这些继承的基类应该(尽可能)基类型或抽象基类。为什么是这样?好吧,Python的开发人员希望避免我们有一百万个新用户类型的情况,例如人们开始检查的FooString和BarInt。这应该避免。
ABC提供了一种允许对象说它是某种东西的方式,比如Integral或String,而不必(必然)必须是一个字符串。
但是,Python的duck typing是建立在实现协议之上的。协议由类中的一个或多个“特殊”(或魔术或dunder)方法定义。确定类的哪些特殊方法可以使用dir(myObj)完成:
>>> dir(itertools.tee)
['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__text_signature__']
或者,甚至更好,在可能的情况下,只是尝试用它做一些事情,如果它失败了,你知道它不是一个鸭子:
try: duck(something)
except: print("Not a duck!")
答案 3 :(得分:2)
我们假设我们定义了一个班级MyClass
:
class MyClass(object):
pass
然后我们定义一个覆盖该类的函数:
def MyClass(x=MyClass):
return x()
如果我们调用该函数,我们将获得原始MyClass
的实例:
>>> instance = MyClass()
>>> type(instance)
<class '__main__.MyClass'>
看起来MyClass
是一个类,因为它的返回值的类型具有相同的名称,但请看一下:
>>> type(MyClass)
<type 'function'>
MyClass
是一个返回MyClass
实例的函数,但它们是不同的。与tee
完全相同。 tee
是一个返回tee
实例的函数。当您看到该实例的类型tee
时,您实际上并未检查类或类型;你正在检查一个功能。 isinstance()
不会允许,因此错误。获得该类的方法是创建一个实例:
>>> tee = type(itertools.tee(())[0])
>>> isinstance(one, tee)
True
答案 4 :(得分:-1)
tee
是一个返回非itertools.tee
实例的函数。检查实例的类名的一种方法是(有点hacky):
>> one.__class__.__name__ == "tee"
True