我知道类是元类的实例,并且__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()
很好,因为URL传播得很好,因为我确实有
Foo : https://stackoverflow.com/
Bar : https://stackoverflow.com/
Baz : https://stackoverflow.com/
我现在有一些我不太了解的内容:
[Class Foo
在2秒后写入]
[Class Bar
再写2秒钟]
[Class Baz
的写入再过2秒钟
因此,元类被执行了3次。这必须说明,由于__new__
负责创建类,因此必须每次运行3次。
我对吗?
如何避免它并使它仅运行一次?
您在这里实际上不需要元类。假设您希望URL
是class属性,而不是实例属性,则只需要使用合适的__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)