gpt4 book ai didi

python - 为什么要使用 __prepare__ 方法来获取类的命名空间?

转载 作者:太空狗 更新时间:2023-10-29 18:06:25 33 4
gpt4 key购买 nike

注意 这个问题与 Python 3 Enum 数据类型无关,它只是我正在使用的示例。

PEP 3115 Python 3 添加了 __prepare__ 1 方法到 type 以允许在创建类时使用自定义命名空间。例如,新的 Enum 数据类型使用 __prepare__ 返回私有(private) _EnumDict 的实例以用作新的 Enum 类的命名空间。

但是,我看到了几个关于 EnumMeta 的 SO2 被子类化的例子,为元类 __new__ 中的类创建了一个新的命名空间方法,但不是调用 __prepare__ 方法来获取新的命名空间,而是使用 type(clsdict)()。这样做有什么风险吗?


1 __prepare__ 的签名:

@classmethod
def __prepare__(metacls, cls, bases, **kwds):

对于__new__:

def __new__(metacls, cls, bases, clsdict, **kwds):

2 使用 type(clsdict) 的示例:

来自 this answer

class CountryCodeMeta(enum.EnumMeta):
def __new__(metacls, cls, bases, classdict):
data = classdict['data']
names = [(country['alpha-2'], int(country['country-code'])) for country in data]

--> temp = type(classdict)()
for name, value in names:
temp[name] = value

excluded = set(temp) | set(('data',))
temp.update(item for item in classdict.items() if item[0] not in excluded)

return super(CountryCodeMeta, metacls).__new__(metacls, cls, bases, temp)

最佳答案

是的,有风险。

通过调用 __prepare__ 而不是 type(clsdict)() 获取新命名空间至少有两个原因:

  • 当在 Python 2 上运行时 clsdict 是一个 dict,而原始的 __prepare__ 从来没有以 ( __prepare__ 仅适用于 Python 3)——换句话说,如果 __prepare__ 返回普通字典以外的内容,则 type(clsdict)() 不会明白了。

  • __prepare__clsdict 上设置的任何属性在使用 type(clsdict)() 时都不会设置;即,如果 __prepare__ 执行 clsdict.spam = 'eggs' 那么 type(clsdict)() 将不会有 spam 属性。请注意,这些属性在命名空间本身上供元类使用,并且在命名空间中不可见。

总结:有充分的理由使用 __prepare__() 来获取正确的类字典,而没有理由使用 type(clsdict)() 快捷方式。

关于python - 为什么要使用 __prepare__ 方法来获取类的命名空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43821562/

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