python typing ignore - Каковы различия между типами () и isinstance ()?





3 Answers

Вот почему isinstance лучше, чем type :

class Vehicle:
    pass

class Truck(Vehicle):
    pass

в этом случае объект грузовика является транспортным средством, но вы получите следующее:

isinstance(Vehicle(), Vehicle)  # returns True
type(Vehicle()) == Vehicle      # returns True
isinstance(Truck(), Vehicle)    # returns True
type(Truck()) == Vehicle        # returns False, and this probably won't be what you want.

Другими словами, isinstance верно и для подклассов.

Также см .: Как сравнить тип объекта в Python?

comments pep 484

Каковы различия между этими двумя фрагментами кода? Использование type() :

import types

if type(a) is types.DictType:
    do_something()
if type(b) in types.StringTypes:
    do_something_else()

Использование isinstance() :

if isinstance(a, dict):
    do_something()
if isinstance(b, str) or isinstance(b, unicode):
    do_something_else()



Последнее предпочтительнее, поскольку оно правильно обрабатывает подклассы. Фактически, ваш пример можно записать еще проще, потому что второй параметр isinstance() может быть кортежем:

if isinstance(b, (str, unicode)):
    do_something_else()

или, используя basestring абстрактный класс:

if isinstance(b, basestring):
    do_something_else()



Для реальных различий мы можем найти его в code , но я не могу найти реализацию поведения по умолчанию isinstance() .

Однако мы можем получить аналогичный abc.__instancecheck__ соответствии с __instancecheck__ .

Сверху abc.__instancecheck__ , после использования теста ниже:

# file tree
# /test/__init__.py
# /test/aaa/__init__.py
# /test/aaa/aa.py
class b():
pass

# /test/aaa/a.py
import sys
sys.path.append('/test')

from aaa.aa import b
from aa import b as c

d = b()

print(b, c, d.__class__)
for i in [b, c, object]:
    print(i, '__subclasses__',  i.__subclasses__())
    print(i, '__mro__', i.__mro__)
    print(i, '__subclasshook__', i.__subclasshook__(d.__class__))
    print(i, '__subclasshook__', i.__subclasshook__(type(d)))
print(isinstance(d, b))
print(isinstance(d, c))

<class 'aaa.aa.b'> <class 'aa.b'> <class 'aaa.aa.b'>
<class 'aaa.aa.b'> __subclasses__ []
<class 'aaa.aa.b'> __mro__ (<class 'aaa.aa.b'>, <class 'object'>)
<class 'aaa.aa.b'> __subclasshook__ NotImplemented
<class 'aaa.aa.b'> __subclasshook__ NotImplemented
<class 'aa.b'> __subclasses__ []
<class 'aa.b'> __mro__ (<class 'aa.b'>, <class 'object'>)
<class 'aa.b'> __subclasshook__ NotImplemented
<class 'aa.b'> __subclasshook__ NotImplemented
<class 'object'> __subclasses__ [..., <class 'aaa.aa.b'>, <class 'aa.b'>]
<class 'object'> __mro__ (<class 'object'>,)
<class 'object'> __subclasshook__ NotImplemented
<class 'object'> __subclasshook__ NotImplemented
True
False

Я получаю этот вывод, для type :

# according to `abc.__instancecheck__`, they are maybe different! I have not found negative one 
type(INSTANCE) ~= INSTANCE.__class__
type(CLASS) ~= CLASS.__class__

Для isinstance :

# guess from `abc.__instancecheck__`
return any(c in cls.__mro__ or c in cls.__subclasses__ or cls.__subclasshook__(c) for c in {INSTANCE.__class__, type(INSTANCE)})

BTW: лучше не смешивать использование relative and absolutely import , использовать absolutely import из project_dir (добавленный sys.path )




Related