避免每次都调用__new __

问题描述 投票:1回答:1

我知道类是元类的实例,并且__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秒钟]

    [Class Baz的写入再过2秒钟

因此,元类被执行了3次。这必须说明,由于__new__负责创建类,因此必须每次运行3次。

我对吗?

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

python metaclass
1个回答
1
投票

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

class Base:
    def __init_subclass__(cls, /, url):
        super().__init_subclass__(cls)
        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)
© www.soinside.com 2019 - 2024. All rights reserved.