- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我注意到我不能以我想要的方式将 __init_subclass__
与 Django 模型类一起使用。看起来元类在父类的 __init_subclass__
方法运行时还没有完成子类的创建。虽然我明白问题是什么,并且可以通过制作自定义元类来规避它,但我不明白的是为什么!
在我看来,我倾向于认为像 __new__
这样的调用应该在 __init__
这样的调用发生之前完成。但这不是元类和 __init_subclass__
的情况,如下所示:
class MetaMeta(type):
print('parsing MetaMeta')
def __call__(cls, *args, **kwargs):
print('entering MetaMeta.__call__')
instance = super().__call__(*args, **kwargs)
print('leaving MetaMeta.__call__')
return instance
class Meta(type, metaclass=MetaMeta):
print('parsing Meta')
def __init__(self, *args, **kwargs):
print(' entering Meta.__init__')
super().__init__(*args, **kwargs)
print(' leaving Meta.__init__')
def __new__(cls, *args, **kwargs):
print(f' entering Meta.__new__')
instance = super().__new__(cls, *args, **kwargs)
print(' leaving Meta.__new__')
return instance
class Parent(object, metaclass=Meta):
print('parsing Parent')
def __init_subclass__(cls, *args, **kwargs):
print(' entering Parent.__init_subclass__')
super().__init_subclass__(*args, **kwargs)
print(' leaving Parent.__init_subclass__')
class Child(Parent):
print('parsing Child')
结果是:
parsing MetaMeta
parsing Meta
parsing Parent
entering MetaMeta.__call__
entering Meta.__new__
leaving Meta.__new__
entering Meta.__init__
leaving Meta.__init__
leaving MetaMeta.__call__
parsing Child
entering MetaMeta.__call__
entering Meta.__new__
entering Parent.__init_subclass__
leaving Parent.__init_subclass__
leaving Meta.__new__
entering Meta.__init__
leaving Meta.__init__
leaving MetaMeta.__call__
在 __init_subclass__
被调用后,元类仍然可以在 Meta.__new__
中设置类。这对我来说似乎很奇怪。为什么会这样,有没有办法在 Parent
(没有自定义元类)中提供完全在 Meta.__new__
之后(可能在 Meta.__init__
)?
还是我完全遗漏了什么?
仅供引用,我找到了一些相关主题,但不是我要找的:
也许问这个问题的更简洁的方式是“为什么 Python(至少 v3.9)有 Meta.__new__
调用 Parent.__init_subclass__
,而不是有MetaMeta.__call__
在 __new__
完成后立即调用它?
请注意,在询问之后,我确实找到了一些关于这个主题的 python.org 讨论,但我认为他们没有阐明原因:
最佳答案
棘手。
所以,它是这样的,因为它是用语言制作的。在为类创建过程添加功能时,人们不允许自定义 __init_subclass__
或描述符 __set_name__
或计算最终线性化 (mro):即所有这些都在 type.__new__
中同时完成 - 任何编写的元类都必须在某个时候调用 type.__new__
。
但是,有一个可能的解决方法:如果 type.__new__
不会“看到”__init_subclass__
方法,则不会调用它。
因此,子元类有可能隐藏__init_subclass__
,调用父类__new__
,然后在离开它自己的__new__
之前> 恢复并调用 __init_subclass__
。
所以,如果问题特别是你需要 __init_subclass__
在 Django 的元类 __new__
完全完成后运行,我可以想到两个选项,它们都涉及继承自Django 的 ORM 元类,对其进行修改,并将其用作模型的元类。
那么第一个选项就是在你的项目中使用不同于 __init_subclass__
的另一个方法名。您的自定义元类调用 super().__new__()
,Django 和 Python 做他们的事情,您调用您的 __init_subclass2__
(或您选择的任何名称)。我认为这是最易于维护和最直接的方法。
第二个选项是我之前提到的:您的__new__
方法检查所有基础是否出现__init_subclass__
,然后暂时从它们所在的类中删除,存储原来的方法,调用super().__new__()
,然后恢复__init_subclass__
方法,之后再调用。这具有在层次结构中使用现有 __init_subclass__
的优势(只要类本身是用 Python 而不是 native 代码编写的:在这种情况下,暂时删除该方法将不起作用) .它有一个严重的缺点,你必须自己扫描 mro(你将不得不重新进行线性化)搜索所有现有的 __init_subclass__
并在之后恢复它们 - 可能有一些难以发现的极端情况.
关于python - 为什么 `type.__new__` 调用 `__init_subclass__` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66480847/
为什么下面的代码会出错? class Foo: def __new__(cls, *args, **kwargs): print("Creating Instance")
Documentation for object.__new__(cls[, ...]) says: Called to create a new instance of class cls. __
编码异常类,我遇到了这个错误: TypeError: object.__new__(A) 不安全,使用 Exception.__new__() 这里有一个类似的问题: TypeError: objec
以下是使用 PyCharm Community Edition 中的 Tkinter 在 Python 3.0 中对 Conway 的生命游戏的不完整实现。 程序由四个文件组成: Cell.py:包含
阅读本文时:What is a metaclass in Python? ,我正在学习使用 __new__ 使用以下代码段:- class a(object): pass a.__new__(
前言 我想要具有以下属性的 2 个类 Interval 和 Segment: Interval 可以有 start 和 end 点,它们中的任何一个都可以被包含/排除(我已经使用必需的标志参数实现了这
我知道当我们通过 super 方法调用父方法时,我们可以忽略绑定(bind)方法中的“self”参数,如下所示: class Foo(object): def __init__(self):
假设以下代码: class NumStorage(object): def __new__(cls, *nargs): name = cls.__name__
嗨,我一直收到这个错误,我不知道如何避免。 我有以下代码: class retrieve_account_data(Thread): _account_queue = None _di
假设我有一些调用 __new__ 的类,我如何才能很好地使用 mro 并根据需要调用父类(super class)的 __new__(带参数),但不使用附加参数调用 object.__new__?例如
我正在尝试像这样深度复制我的 igraph 对象: copy.deepcopy(graph) 其中 graph 是 igraph 对象,一个只有几个顶点的完整图。但是我得到这个错误: Fi
假设我有以下代码用于处理个人和国家/地区之间的链接: from dataclasses import dataclass @dataclass class Country: iso2 : st
我知道类是元类的实例,并且 __new__ 在 __init__ 之前运行,因为,您必须在初始化它之前创建一个实例。 现在想象一下: import time class ConfigurationsM
使用Python元类A创建一个新类B。 当C继承B时,为什么调用A的__new__方法? class A(type): def __new__(cls, name, bases, attrs)
案例1: class Person: def __new__(cls, *args, **kwargs): print "called" return supe
我可以知道为什么 myClass1 和 myClass2 在覆盖 __new__() 方法时表现不同吗?推荐使用哪种方式来编写类,为什么?我认为 myClass1(): 甚至没有调用 __new__(
当__new__返回类的实例时,一切正常,我们可以毫无问题地创建子类: class A: def __new__(cls, p1, p2): self = object.__n
如何编写默认的 __new__ 并进行一些小的更改,如下所示: class A: def __new__(cls, *args, **kwargs): retval = sup
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 8 年前。 Improve this qu
我一直在努力理解__new__ 和元编程。所以我看了一下官方的 python 源代码。 http://hg.python.org/cpython/file/2.7/Lib/fractions.py 分
我是一名优秀的程序员,十分优秀!