python - 避免每次都调用 __new__

标签 python metaclass

我知道类是元类的实例,并且 __new____init__ 之前运行,因为,您必须在初始化它之前创建一个实例。

现在想象一下:

import time
class ConfigurationsMeta(type):
    def __new__(cls, name, bases, attr):
        # Potentially a long task here (eg: Getting value from a web service)
        time.sleep(2)

        # Which class inherit from me (debug)
        print(f'Class {name}')

        config = super().__new__(cls, name, bases, attr)

        #Set a variable to be propagated (Variable coming from web service)
        setattr(config, "URL", "https://stackoverflow.com/")

        return config

class Foo(metaclass=ConfigurationsMeta):
    def __init__(self):
        print(f'{__class__.__name__} : {self.URL}')

class Bar(Foo):
    def __init__(self):
        print(f'{__class__.__name__} : {self.URL}')

class Baz(Bar):
    def __init__(self):
        print(f'{__class__.__name__} : {self.URL}')

e = Foo()
s = Bar()
c = Baz()
  1. 很好,因为 URL 传播得很好,就像我所做的那样

    Foo : https://stackoverflow.com/
    Bar : https://stackoverflow.com/
    Baz : https://stackoverflow.com/
    
  2. 我现在确实有一些不太明白的事情:

    Class Foo 在 2 秒后写入

    Class Bar 在另外 2 秒后写入

    Baz类又过了2秒终于写入了

所以元类被执行了三次。 这必须说明,由于 __new__ 负责创建类,所以每次都必须运行它,所以运行三次。

我说得对吗?

如何避免它并使其仅运行一次?

最佳答案

这里实际上并不需要元类。假设您希望 URL 成为 class 属性,而不是实例属性,则只需使用合适的 __init_subclass__ 定义来定义基类。应首先检索 URL 并将其作为参数传递给 __init_subclass__(通过 class 语句中的关键字参数)。

class Base:
    def __init_subclass__(cls, /, url=None):
        super().__init_subclass__(cls)
        if url is not None:
            cls.URL = url


some_url = call_to_webservice()


class Foo(Base, url=some_url):
    pass


class Bar(Foo):
    pass


class Baz(Bar):
    pass

如果 URL 应该是实例属性,则将 __init_subclass__ 替换为 __init__:

some_url = call_to_webservice()

class Base:
    def __init__(self, /, url):
        self.url = url

class Foo(Base):
    pass

f = Foo(some_url)

关于python - 避免每次都调用 __new__,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59881445/

相关文章:

Python:在为 __init__subclass__() 提供参数的同时动态创建类

python - 是否有更 Pythonic 的方式通过字符串名称访问函数?

python - 如何将所有 .sass 请求匹配到 Pylons 中的特定 Controller ?

python - 选择 Pandas 中的平均列(同时排除一列)

python - 自动将枚举成员的值设置为其名称

python - 为什么元类应该从类型继承?

python - 为什么 Pylint 在使用元类定义的属性时会出错?

ruby - 在 Ruby 中,向实例的单例类添加方法的用例是什么?

python - 如何在python中将文本转换为语音

python - 是什么让这个安全描述符变坏了?