gpt4 book ai didi

python - 实现具有与 `type` 不同签名的元类的正确方法是什么?

转载 作者:太空狗 更新时间:2023-10-30 01:11:17 26 4
gpt4 key购买 nike

假设我想实现一个应该作为类工厂的元类。但不同于 type构造函数,它有 3 个参数,我的元类应该可以在没有任何参数的情况下调用:

Cls1 = MyMeta()
Cls2 = MyMeta()
...

为此我定义了一个自定义 __new__没有参数的方法:

class MyMeta(type):
def __new__(cls):
return super().__new__(cls, 'MyCls', (), {})

但问题是 python 会自动调用 __init__方法具有与 __new__ 方法相同的参数,因此尝试调用 MyMeta() 最终会抛出异常:

TypeError: type.__init__() takes 1 or 3 arguments

这是有道理的,因为可以使用 1 或 3 个参数调用 type。但是解决这个问题的正确方法是什么?我看到 3(4?)个选项:

  • 我可以向我的元类添加一个空的 __init__ 方法,但由于我不确定 type.__init__ 是否做了任何重要的事情,这可能不是一个好主意.
  • 我可以实现调用 super().__init__(cls.__name__, cls.__bases__, vars(cls))__init__ 方法。
  • 我可以使用元元类并覆盖它的 __call__ 方法,而不是搞乱 __new____init__
  • 额外选项:也许我不应该尝试更改签名?

所以我的问题是:我列出的 3 个解决方案是否正确,或者其中是否隐藏了任何细微的错误?哪种解决方案最好(即最正确)?

最佳答案

偏离父签名的接口(interface)是 questionable design在常规类(class)中也是如此。您不需要元类的额外复杂性来陷入这种困惑 - 您可以通过子类化 datetime 或其他任何东西来导致相同的 new/init 困惑。

I want to have a metaclass and an easy way to create instances of that metaclass.

Python 中的常用模式是使用 from_something 类方法编写工厂。以从不同的初始化签名创建日期时间实例为例,例如 datetime.fromtimestamp ,但您还有许多其他示例(dict.fromkeysint.from_bytesbytes.fromhex...)

这里没有什么特定于元类的,所以使用相同的模式:

class MyMeta(type):
@classmethod
def from_no_args(cls, name=None):
if name is None:
name = cls.__name__ + 'Instance'
return cls(name, (), {})

用法:

>>> class A(metaclass=MyMeta):
... pass
...
>>> B = MyMeta.from_no_args()
>>> C = MyMeta.from_no_args(name='C')
>>> A.__name__
'A'
>>> B.__name__
'MyMetaInstance'
>>> C.__name__
'C'

关于python - 实现具有与 `type` 不同签名的元类的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52185979/

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