gpt4 book ai didi

python - 避免每次都调用 __new__

转载 作者:行者123 更新时间:2023-12-01 06:31:38 26 4
gpt4 key购买 nike

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

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