2016-03-09 2 views
0

В качестве части меморандума, у меня есть генератор, I tee его, и я должен проверить его тип с помощью isinstnace.isinstance with tee objects

>>> 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?

ответ

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

itertools.tee - это функция, а не класс (см. type(itertools.tee)). Он возвращает объекты, которые (несколько сбивчиво) экземпляры класса tee, но этот класс недоступен в пространстве имен itertools. Я просто возьму его из примера, используя type(). Если у вас нет подходящего экземпляра, создайте его. Это, кажется, минимальное количество кода, чтобы получить тип tee:

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

действительно кажется, что tee последовательно использует один и тот же класс для каждого вызова.

+0

ой есть путь, я думаю: P +1 –

4

tee - функция, которая возвращает внутренний тип реализации, используемый Python. В общем, не имеет значения, что это tee или любой другой тип .

Тем не менее, если вам действительно нужно ввести тест, как это, вы можете сделать это, вам просто нужно получить «истинный» тип tee экземпляра так же, как вы проверили тип уже, используя type. Например, для хранения типа tee экземпляров в переменной с именем Tee, вы могли бы сделать:

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

который вызывает tee для получения экземпляров, а затем использует type, чтобы получить свой класс.

Это единственный переносной способ сделать это для записи; фактические типы включают (будучи внутренним исполнением) изменения от выпуска до выпуска; в Python 3.5 у вас есть доступ к необработанному типу как itertools._tee, но, очевидно, в вашей версии он не отображается так.

2

isinstance используется, чтобы проверить, что-то говорит, что это утка, независимо от того, является она утка или нет.

Чтобы ответить на ваш вопрос сразу же, isinstance.tee является методом, а не класс или типа или кортежа типов:

>>> type(itertools.tee) 
<class 'builtin_function_or_method'> 

(На самом деле, на мою версию питона, класс вообще был удален из списка вариантов). Python - это «язык, уложенный языком». В принципе, для того, чтобы «isststance» сказать, что что-то является примером другого, оно должно каким-то образом унаследовать его.

Пример:

>>> 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) методами в классе. Определение того, какие специальные методы являются частью класса может быть сделано с дир (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!") 
-1

tee это функция, которая возвращает экземпляр, который не itertools.tee. Один из способов проверить, что (несколько Hacky) запрашивать имя класса экземпляра:

>> one.__class__.__name__ == "tee" 
True 
+1

Как я заметил на другой ответ, это невероятно хрупким; внутреннее имя типа изменяется с момента выпуска на выпуск (это деталь реализации, а не часть спецификации, и может быть изменена в любое время); в Python 3.5, например, имя типа '_tee'. – ShadowRanger