gpt4 book ai didi

python - 为什么 python isinstance() 对于基类是可传递的,而对于元类是不可传递的?

转载 作者:行者123 更新时间:2023-12-03 17:10:26 26 4
gpt4 key购买 nike

我是元类的新手,可能会以意想不到的方式使用它们。我对 isinstance() 的事实感到困惑方法在处理子类时似乎具有传递行为,但在处理元类时没有。
在第一种情况下:

class A(object):
pass

class B(A):
pass

class C(B):
pass

ic = C()
意味着 isinstance(ic,X)X 是正确的等于 A , BC .
另一方面,这是一个元类示例:
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
那就是 MyClassMetaDataElement 的一个实例元类和 my_instanceMyClass 的一个实例类但不属于 MetaDataElement .
我的解释正确吗?对此有简单的解释吗?

最佳答案

令人困惑的是 MyClass不是 DataElementBase 的“实例” .它是元类的一个实例:MetaDataElement ,以及该元类的所有父类(super class)的实例(即:“类型”和“对象”)。就像“普通”类的实例会发生什么一样:
将您的代码片段粘贴到交互式解释器中,我可以这样做:

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”的关系是“父类(super class)”。所以,如果你问它是否是 DataElementBase 的子类,你会得到 True:
In [100]: issubclass(MyClass, DataElementBase)
Out[100]: True

类基作为调用 type.__new__ 的第三个参数传递。 .
所以,换句话说:“元类”是“用来构建类的类”,它与创建的类的继承链无关。相反,给定的对象将始终是其类的任何“父类(super class)”的实例。元类不是其类的父类(super class)。
一旦你理解了这一点,你就会注意到“isinstance”和“issubclass”的行为在“非元”类及其实例、“元类”和通过它们创建的类之间是相同的。

在一个不相关的通知中,尽管您的代码按原样工作,但不鼓励这样做。:元类的签名 __new__方法应该符合 type.__new__的签名- 并接收元类本身、名称、基类、命名空间和可选的关键字参数。
您编写它的方式,将您的元类与此签名分开,迫使您的代码按照您所做的方式声明类:通过调用显式实例化元类。它不能用作从 class 创建新类的元类。语句及其主体 - 在这种情况下,Python 使用 type.__new__ 使用的参数调用元类。 .

关于python - 为什么 python isinstance() 对于基类是可传递的,而对于元类是不可传递的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64361857/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com