Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在本例中,.\uu new\uu函数是如何工作的?_Python_Python 3.x_Class_Metaclass - Fatal编程技术网

Python 在本例中,.\uu new\uu函数是如何工作的?

Python 在本例中,.\uu new\uu函数是如何工作的?,python,python-3.x,class,metaclass,Python,Python 3.x,Class,Metaclass,我在理解.strongnewmagic方法如何创建类时遇到了一些困难。下面是我正在使用的API的一个示例,该API使用元类从数据库中的信息动态创建对象 class Metaclass(type): def __new__(cls, name, bases, dict_): print(f' cls - {cls}') print(f' name - {name}') print(f' bases - {bases}') re

我在理解.strongnewmagic方法如何创建类时遇到了一些困难。下面是我正在使用的API的一个示例,该API使用元类从数据库中的信息动态创建对象

class Metaclass(type):
    def __new__(cls, name, bases, dict_):
        print(f' cls - {cls}')
        print(f' name - {name}')
        print(f' bases - {bases}')
        return super(Metaclass, cls).__new__(cls, name, bases, dict_)

class MyObject(object, metaclass=Metaclass):
    pass

class PrimaryObject(MyObject):
    pass

class SecondaryObject(MyObject):
    pass

test = PrimaryObject()
运行此代码将导致实例化PrimaryObject,该对象继承自MyObject,而MyObject又继承自元类。然后调用元类中的新magic方法,该方法对从元类继承的所有对象(即使是未调用的对象)进行三次迭代:

<class '__main__.Metaclass'>
MyObject
(<class 'object'>,)
<class '__main__.Metaclass'>
PrimaryObject
(<class '__main__.MyObject'>,)
<class '__main__.Metaclass'>
SecondaryObject
(<class '__main__.MyObject'>,)
<__main__.PrimaryObject object at 0x000002214A6786D0>

肌体
(,)
主要对象
(,)
第二对象
(,)
新的方法如何接收这些参数,因为没有向它传递任何信息?它们是从调用它的对象解析出来的吗?如果是这样的话,它为什么以及如何遍历从该对象继承但未稳定的其他对象(SecondaryObject)

谢谢,“…这反过来又继承了元类…”

这是你假设的错误部分。 这些类都不是从元类“继承”的

元类用于构建它们—类本身—仅一次 每节课。这就是调用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
的时候:当Python执行
语句(以及类主体)时

实例化
PrimaryObject
将不再调用元类
\uuuuu new\uuuuu
——只需在那里添加另一个print语句,在
test=…
行之前,您将看到这一点

但是,如果您希望在创建使用元类创建的类的实例时调用元类上的方法,则该方法是
\uuuuu call\uuuuuu
方法,而不是
\uuu new\uuuuu
。当您在元类调用中调用
super()。\uuuu-call\uuuuuu(…)
时,它将运行
type.\uuuu-call\uuuuuuuuuuuu
,这反过来又是运行类
\uuuuu-new\uuuuuuuuuuu
init\uuuuuuuuuuu
方法的操作,创建一个新实例

print(“定义元类”)
类元类(类型):
定义新(cls、名称、基础、目录):
打印(f'cls-{cls}')
打印(f'名称-{name}')
打印(f'bases-{bases}')
返回超级(元类,cls)。\uuuu新的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
定义呼叫(cls,*参数,**千瓦):
打印(f“创建{cls.\uuuu name\uuuuuu}的新实例”)
return super()
打印(“创建使用元类的类”)
类MyObject(对象,元类=元类):
通过
类PrimaryObject(MyObject):
通过
类SecondaryObject(MyObject):
通过
打印(“创建类实例”)
test=PrimaryObject()

元类是类的类型。根据您的代码,比较

>>> type(MyObject)
<class '__main__.Metaclass'>
>>> type(int)
<class 'type'>
在Python语言参考中概述


与所有类型一样,对类型本身的调用调用调用其
\uuuuu new\uuuuu
方法,因此

MyObject = Metaclass('MyObject', (), {})
大致相当于

MyObject = Metaclass.__new__(Metaclass, 'MyObject', (), {})
if isinstance(MyObject, Metaclass):
    MyObject.__init__()

这是一个元类,它是在创建类时调用的,而不是在创建实例时调用的。@jonrsharpe我认为最好使用“已定义”而不是“已创建”,即“已定义类”@DeepSpace不确定是什么使它最清晰,但此时正在创建类型类的实例。
MyObject
元类的实例;查看
type(MyObject)
的值,与类似
type(int)
的值进行比较。
MyObject = Metaclass.__new__(Metaclass, 'MyObject', (), {})
if isinstance(MyObject, Metaclass):
    MyObject.__init__()