为什么 python isinstance() 可传递给基数 类 而不传递给 meta类?
Why is python isinstance() transitive with base classes and intransitive with metaclasses?
我是 metaclasses 的新手,可能会以意想不到的方式使用它们。我感到困惑的是 isinstance()
方法在处理 subclasses 时似乎具有传递行为,但在处理 metaclasses.
时却没有
第一种情况:
class A(object):
pass
class B(A):
pass
class C(B):
pass
ic = C()
暗示 isinstance(ic,X)
对于 X
等于 A
、B
或 C
.
为真
另一方面,这是一个元class示例:
class DataElementBase(object):
def __init__(self,value):
self.value = self.__initialisation_function__(value)
class MetaDataElement(type):
def __new__(cls,name,initialisation_function, helptext ):
result = type.__new__(cls,name,(DataElementBase,), dict(help=helptext) )
result.__initialisation_function__ = staticmethod(initialisation_function)
return result
### test code ####
# create a class from the metaclass
MyClass = MetaDataElement( 'myclass', float, "Value is obtained as float of user input" )
# create an instance of the class
my_instance = MyClass( '4.55' )
print ( 'MyClass is instance of MetaDataElement? %s' % isinstance( MyClass, MetaDataElement ) )
print ( 'MyClass is instance of DataElementBase? %s' % isinstance( MyClass, DataElementBase ) )
print ( 'my_instance is instance of MyClass? %s' % isinstance( my_instance, MyClass ) )
print ( 'my_instance is instance of MetaDataElement? %s' % isinstance( my_instance, MetaDataElement ) )
print ( 'my_instance is instance of DataElementBase? %s' % isinstance( my_instance, DataElementBase ) )
产量:
MyClass is instance of MetaDataElement? True
MyClass is instance of DataElementBase? False
my_instance is instance of MyClass? True
my_instance is instance of MetaDataElement? False
my_instance is instance of DataElementBase? True
也就是说,MyClass
是MetaDataElement
metaclass的一个实例,而my_instance
是MyClass
class的一个实例] 但不是 MetaDataElement
.
我的解释正确吗?有没有简单的解释?
isinstance
的基本目的是检查对象是否提供 接口 。例如,(类型的对象)DataElementBase
的接口可能包括它具有 value
属性。事实上,my_instance.value
是 4.55。
(类型的对象)MetaDataElement
的接口是它是一个 class,除其他外,它继承自 DataElementBase
. my_instance
是这样的class吗?不;它甚至不能像 classes 那样被调用。它是这样一个 class 的一个 object,但是 isinstance(my_interface, MetaDataElement)
意味着它 是 这样一个 class.
令人困惑的是 MyClass
不是 DataElementBase
的“实例”。它是 metaclass: MetaDataElement
的实例,以及该 metaclass 的所有超classes 的实例(即:“type”和“object” ).就像“普通”实例发生的情况一样 classes:
将您的代码片段粘贴到交互式解释器中我可以做到:
In [96]: isinstance(MyClass, MetaDataElement)
Out[96]: True
In [97]: isinstance(MyClass, type)
Out[97]: True
In [98]: isinstance(MyClass, object)
Out[98]: True
In [99]: MyClass.__mro__
Out[99]: (__main__.myclass, __main__.DataElementBase, object)
“DataElementBase”与“MyClass”的关系是“superclass”。所以,如果你问它是否是 DataElementBase 的子class,你会得到 True:
In [100]: issubclass(MyClass, DataElementBase)
Out[100]: True
class 碱基作为调用 type.__new__
的第三个参数传递。
所以,换句话说:一个“metaclass”是“用来构建一个class的class”,与继承链无关创建的class。相反,给定对象将始终是其 class 的任何“superclass”的实例。 metaclass 不是其 class.
的超class
一旦理解了这一点,您就会注意到“isinstance”和“issubclass”的行为在“非元”classes 及其实例中是相同的,而“元classes" 和通过它们创建的 classes。
在一条不相关的通知中,尽管您的代码按原样工作,但不鼓励这样做。:metaclass __new__
方法的签名应符合 type.__new__
- 并接收 metaclass 本身、名称、基础、命名空间和可选关键字参数。
你写的方式,从这个签名中分离你的元class强制你的代码声明classes你的方式:通过显式实例化元class称呼。它不能用作从 class
语句及其主体创建新的 class 的 metaclass - 在这种情况下,Python 调用 metaclass 与 type.__new__
.
使用的参数
我是 metaclasses 的新手,可能会以意想不到的方式使用它们。我感到困惑的是 isinstance()
方法在处理 subclasses 时似乎具有传递行为,但在处理 metaclasses.
第一种情况:
class A(object):
pass
class B(A):
pass
class C(B):
pass
ic = C()
暗示 isinstance(ic,X)
对于 X
等于 A
、B
或 C
.
另一方面,这是一个元class示例:
class DataElementBase(object):
def __init__(self,value):
self.value = self.__initialisation_function__(value)
class MetaDataElement(type):
def __new__(cls,name,initialisation_function, helptext ):
result = type.__new__(cls,name,(DataElementBase,), dict(help=helptext) )
result.__initialisation_function__ = staticmethod(initialisation_function)
return result
### test code ####
# create a class from the metaclass
MyClass = MetaDataElement( 'myclass', float, "Value is obtained as float of user input" )
# create an instance of the class
my_instance = MyClass( '4.55' )
print ( 'MyClass is instance of MetaDataElement? %s' % isinstance( MyClass, MetaDataElement ) )
print ( 'MyClass is instance of DataElementBase? %s' % isinstance( MyClass, DataElementBase ) )
print ( 'my_instance is instance of MyClass? %s' % isinstance( my_instance, MyClass ) )
print ( 'my_instance is instance of MetaDataElement? %s' % isinstance( my_instance, MetaDataElement ) )
print ( 'my_instance is instance of DataElementBase? %s' % isinstance( my_instance, DataElementBase ) )
产量:
MyClass is instance of MetaDataElement? True
MyClass is instance of DataElementBase? False
my_instance is instance of MyClass? True
my_instance is instance of MetaDataElement? False
my_instance is instance of DataElementBase? True
也就是说,MyClass
是MetaDataElement
metaclass的一个实例,而my_instance
是MyClass
class的一个实例] 但不是 MetaDataElement
.
我的解释正确吗?有没有简单的解释?
isinstance
的基本目的是检查对象是否提供 接口 。例如,(类型的对象)DataElementBase
的接口可能包括它具有 value
属性。事实上,my_instance.value
是 4.55。
(类型的对象)MetaDataElement
的接口是它是一个 class,除其他外,它继承自 DataElementBase
. my_instance
是这样的class吗?不;它甚至不能像 classes 那样被调用。它是这样一个 class 的一个 object,但是 isinstance(my_interface, MetaDataElement)
意味着它 是 这样一个 class.
令人困惑的是 MyClass
不是 DataElementBase
的“实例”。它是 metaclass: MetaDataElement
的实例,以及该 metaclass 的所有超classes 的实例(即:“type”和“object” ).就像“普通”实例发生的情况一样 classes:
将您的代码片段粘贴到交互式解释器中我可以做到:
In [96]: isinstance(MyClass, MetaDataElement)
Out[96]: True
In [97]: isinstance(MyClass, type)
Out[97]: True
In [98]: isinstance(MyClass, object)
Out[98]: True
In [99]: MyClass.__mro__
Out[99]: (__main__.myclass, __main__.DataElementBase, object)
“DataElementBase”与“MyClass”的关系是“superclass”。所以,如果你问它是否是 DataElementBase 的子class,你会得到 True:
In [100]: issubclass(MyClass, DataElementBase)
Out[100]: True
class 碱基作为调用 type.__new__
的第三个参数传递。
所以,换句话说:一个“metaclass”是“用来构建一个class的class”,与继承链无关创建的class。相反,给定对象将始终是其 class 的任何“superclass”的实例。 metaclass 不是其 class.
的超class一旦理解了这一点,您就会注意到“isinstance”和“issubclass”的行为在“非元”classes 及其实例中是相同的,而“元classes" 和通过它们创建的 classes。
在一条不相关的通知中,尽管您的代码按原样工作,但不鼓励这样做。:metaclass __new__
方法的签名应符合 type.__new__
- 并接收 metaclass 本身、名称、基础、命名空间和可选关键字参数。
你写的方式,从这个签名中分离你的元class强制你的代码声明classes你的方式:通过显式实例化元class称呼。它不能用作从 class
语句及其主体创建新的 class 的 metaclass - 在这种情况下,Python 调用 metaclass 与 type.__new__
.