【问题标题】:How to access variables defined in subclasses of a class from that class?如何从该类访问在该类的子类中定义的变量?
【发布时间】:2020-12-16 17:17:56
【问题描述】:

我在某处定义了一个基类,可由某些用户扩展。

现在我想访问该用户在其子类中可能定义的变量,以便我可以对它做一些事情。

我尝试使用metaclasses 来解决这个问题

这是设置的示例:

class Meta(type):
    def __new__(cls, name, bases, attrs):
        clsobj = super().__new__(cls, name, bases, attrs)
        print(f'the name of this class is {clsobj.NAME.upper()}')
        return clsobj


class Base(metaclass=Meta):
    pass

class C1(Base):
    NAME = "C1"

if __name__ == "__main__":
    c1 = C1()

但我收到以下错误:

AttributeError: type object 'Base' has no attribute 'NAME'

注意Base 类不应该不知道它的子类变量,而应该只访问它们。

【问题讨论】:

  • 如何在不知道的情况下访问某些内容?
  • @DeepSpace 在 Python 中是可能的。我只是想不出正确的代码;)

标签: python variables subclass metaclass


【解决方案1】:

一种可能的解决方案是(绕过在基类构造过程中出现的错误):

class Meta(type):
    def __new__(cls, name, bases, attrs):
        clsobj = super().__new__(cls, name, bases, attrs)
        if 'NAME' not in vars(clsobj):  # add these lines
            pass                        # add these lines (bypass mechanism)
        else:                           # add these lines
            print(f'the name of this class is {clsobj.NAME.upper()}')          
        return clsobj                   


class Base(metaclass=Meta):
    pass

class C1(Base):
    NAME = "C1"

if __name__ == "__main__":
    c1 = C1()

如果有多个感兴趣的变量,if ... pass ... else .. 变为:

clsattrs = vars(clsobj)
if 'VAR1' not in clsattrs or 'VAR2' not in clsattrs or 'VAR3' not in clsattrs ...:
    pass
else:
    function_on(VAR1)
    function_on(VAR2)
    function_on(VAR3)
    ....
`

我想这更简单,更准确..

但我仍在等待可能更好的解决方案!

【讨论】:

    【解决方案2】:

    以 OP 的自我回答为基础,但更通用(因此无需猜测属性的名称):

    class Meta(type):
        def __new__(cls, name, bases, attrs):
            clsobj = super().__new__(cls, name, bases, attrs)
            for attr, value in vars(clsobj).items():
                if not attr.startswith('__'):  # we probably want to ignore 'magic' attributes
                    print(value)
            return clsobj
    

    【讨论】:

    • 实际上我想对这些属性进行一些计算,而不仅仅是打印它们(这只是为了简化目的)。所以我真的需要知道变量的名称,这样我才能用它做点什么。例如,在这里我需要将 NAME 变量附加到其他字符串并获得结果。
    • @moctarjallo 是什么阻止你使用变量的名称做某事,就像我在检查它是否以 __ 开头时所做的那样?
    • 我明白了。但是您在所有变量上都是looping,然后可能会做if attr == 'NAME' 对吗?凉爽的。但是你需要知道你在寻找什么属性!所以我认为我的解决方案可能会更好(没有循环),因为我只是直接检查if 'NAME' in attrs
    • @moctarjallo 问题是“该用户可能定义的变量”。没有关于NAME 的具体内容。我所做的只是提供一种更通用的方法(如它所说),而不是硬编码潜力,未知的预先值。但是,如果您对某些特定的块感兴趣,我的方法仍然提供更大的灵活性,因为您不再需要 5 个 if-else 块,只需将 and attr in ('x', 'y', 'z') 添加到现有的 if 检查
    • 我明白。但是,如果我要寻找多个变量怎么办?然后我需要在for 循环中有多个if 语句来检索我从attrs 寻找的变量。而在我的解决方案中,您只需要一行 if 语句,但需要多个条件(检查这些变量中的每一个是否存在于 attrs 中)。尽管如此,我明白这个问题并没有准确地说明变量的多样性;我只需要一个变量的解决方案,这足以让我知道如何推广到多个变量;)​​
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    • 2011-01-26
    • 2018-08-15
    • 2012-04-09
    • 1970-01-01
    相关资源
    最近更新 更多