【问题标题】:how to access class' attribute instead of objects如何访问类的属性而不是对象
【发布时间】:2019-08-24 16:51:05
【问题描述】:

假设你有

class c:
    pass
print(c.__call__)

output: <method-wrapper '__call__' of type object at 0x0000023378F28DC8>

我的问题是,如果定义了 __call__,我将无法获得相同的输出
像这样:

class c:
    __call__ = lambda self: None
print(c.__call__)

output: <function c.<lambda> at 0x000002337A069B70>

type.__getattribute__(c, '__call__') 都不起作用

总结一下,我想在两个示例中都首先输出
有可能吗(我猜是通过一些元编程)

【问题讨论】:

    标签: python-3.x class metaprogramming


    【解决方案1】:

    这与使用同名的类变量和实例变量可能遇到的问题相同:

    class Test:
        var = 1             # class variable
    
        def __init__(self):
            self.var = 2    # instance variable with the same name
    
    t = Test()
    print(t.var)     # prints 2, the instance variable, not the class variable
    print(Test.var)  # prints 1, the class variable
    

    在您的第一个示例中,__call__ 方法在元类type 中定义。您正在通过type 的实例、c 类访问它。如果你在c中定义了一个类变量,它本质上是元类视角下的一个实例变量,所以你再也看不到元类中定义的版本了。

    和上面我的类变量代码一样,从元类中获取__call__方法的最好方法是直接命名:type.__call__。如果您认为您可能有其他元类,您可以在该类上调用type,以获取元类而不命名它:type(c).__call__

    请注意,type.__call__ 方法在与普通类中定义的__call__ 方法不同的情况下运行。当你调用类时,解释器运行type.__call__,例如c(),而 c.__call__ 在您调用实例时运行:

    obj = c()  # this is type.__call__
    obj()      # this is where c.__call__ runs
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-15
      相关资源
      最近更新 更多