0

作为记忆机制的一部分,我有一个生成器,我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什么?

4

5 回答 5

4

itertools.tee是一个函数,而不是一个类(参见 参考资料type(itertools.tee))。它返回的对象(有些令人困惑)是tee类的实例,但该类在itertools命名空间中不可用。我只是从一个使用type(). 如果您手边没有实例,请创建一个。这似乎是获取tee类型的最少代码量:

TeeType = type(itertools.tee(())[0])

似乎tee每次调用始终使用相同的类。

于 2016-03-09T01:20:40.727 回答
4

tee是一个返回 Python 使用的内部实现类型的函数。一般来说,它是 atee或任何其他iterator/generator类型都没有关系。

也就是说,如果你真的需要像这样进行类型测试,你可以这样做,你只需要以tee与已经检查类型相同的方式派生实例的“真实”类型,使用type. 例如,要将tee实例类型存储在名为 的变量中Tee,您可以:

Tee = type(itertools.tee(())[0])

它调用tee获取实例,然后用于type获取它们的类。

这是记录的唯一便携方式;实际类型涉及(作为内部实现)从发布到发布的更改;在 Python 3.5 中,您可以访问原始类型 as itertools._tee,但显然在您的版本中,它并没有像那样公开。

于 2016-03-09T01:20:57.703 回答
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 的鸭子类型是建立在实现协议之上的。协议由类中的一个或多个“特殊”(或魔法或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!")
于 2016-03-09T01:22:32.403 回答
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。当您查看该实例是否为 typetee时,您实际上并没有检查类或类型;你正在检查一个功能。 isinstance()不允许这样做,因此错误。获取类的方法是创建一个实例:

>>> tee = type(itertools.tee(())[0])
>>> isinstance(one, tee)
True
于 2016-03-09T01:25:31.197 回答
-1

tee是一个函数,它返回一个不是itertools.tee. 一种检查方法是(有点hacky)查询实例的类名:

>> one.__class__.__name__ == "tee"
True
于 2016-03-09T01:26:10.393 回答