__getattr__ 用于 class 属性?

__getattr__ for class atributes?

对于 class Foo,

class Foo:
    ...

有没有办法在 Foo.XXX(任意 class 属性 XXX,例如 barbar2 等时调用特定方法.) 正在被解析,但不是每当 Foo().XXX(任意实例属性)被解析时?据我所知,重写

def __getattr__(self, a):
    ...

仅适用于第二种情况。我想从 __getattr__ for instances 仅在未找到相应属性时调用这一事实中受益。有谁知道这应该如何解决?我通读了 the manual,但没有发现任何相关内容。

我并不特别关心如果有人试图为 Foo 的任何 class 或实例属性赋值会发生什么。

用例(避免XY):

Class Foo 是一个使者。 Foo 的实例基本上是带有额外步骤的元组。但是,有 Foo 的特殊情况,我想将其存储为 Foo 的 class 属性(我使用特殊的装饰器管理它)。然而, Foo 的特例数量在逐渐增加,但它们之间的差异很小。每当有人需要 Foo.SPECIAL_CASE_123 时调用这个特殊函数对我来说将是非常有效的 code-wise,因为从 "SPECIAL_CASE_123" 到实际特殊情况的映射非常快并且非常类似于映射 "SPECIAL_CASE_456"到其他相应的特例。

您可以尝试使用 @classmethods:

class Foo:        
    @classmethod
    def XXX(self, a):
        return a
print(Foo.XXX('Hello World'))

输出:

Hello World

使用元class 定义classes 的行为方式。具体来说,重新定义 class' __getattr__ 以更改 class 上缺失的属性的处理方式:

# The "Type of Foo"
class MetaFoo(type):
    def __getattr__(cls, item):
        return f"Dynamically handled: {item}"


class Foo(metaclass=MetaFoo):
    REGULAR_CASE_22 = "Catch 22"

print(Foo.REGULAR_CASE_22)     # Catch 22
print(Foo.SPECIAL_CASE_123)    # Dynamically handled: SPECIAL_CASE_123
print(Foo().REGULAR_CASE_22)   # Catch 22
print(Foo().SPECIAL_CASE_123)  # AttributeError: 'Foo' object has no attribute 'SPECIAL_CASE_123'

请注意,某些属性查找,例如 __add__ 等特殊方法,将绕过元class 属性查找。