【问题标题】:How to properly access and set class variables in a derived class?如何在派生类中正确访问和设置类变量?
【发布时间】:2021-08-15 04:38:45
【问题描述】:

假设你有一个 python 类(比如B),它是某个其他类(比如A)的派生类,并且该类A 具有类变量和@classmethods,它们可以帮助您更改或查看这些类变量。我曾假设使用 cls.variable_name = value 语法设置类 A 类变量的 A 类中的 @classmethod 会起作用。

这似乎有时有效,但并不总是让我感到困惑。下面是一个没有像我期望的那样设置类变量的例子。因此我不知道cls.something 将访问什么,所以我必须使用A.something,这似乎我将在@classmethods 中缺少cls.something 的功能。 cls.something在类方法中实际访问的是什么,为什么下面的例子没有设置test类的类变量?

以下带有输出的示例有望证明我的意思:

class Test():
    epf = 'A'

    @classmethod
    def set_formats(cls, p):
        cls.epf = p

    @classmethod
    def form(cls):
        return cls.epf

class Mytest(Test):
        pass

这是输出:

>>>c=Mytest
>>>Test.form()
'A'

>>>c.set_formats(p='a')
>>>Test.epf
'A'

>>>c.form()
'a'

>>>c.epf
'a'

所以在这个例子中,类方法并没有像我预期的那样改变类变量,而是出现了一个实例变量。如果我在没有派生类的情况下执行上述操作,那么它会按预期工作。唔?显然这里遗漏了什么!

现在,如果我将 c.set_formats(p='a', f='A') 更改为 Test.set_formats(p='a', f='A'),它确实可以工作。是不是因为c.set_formats使用了以cls为实例的类方法?

编辑:使代码更小,并根据要求更改了约定。

【问题讨论】:

  • 您应该编辑您的问题以提供minimal reproducible example。有很多不相关的代码使您的问题的中心点难以区分。
  • 如果您在子类上调用类方法,那么cls 参数将是子类,不一定是包含该方法的类。
  • "是不是因为C.set_formats使用了cls作为实例的类方法?"不,cls 将是 实例的类,就像使用类方法一样。在这种情况下,它将与mytest.set_formats(p='a', f='A') 相同,即在mytest 上设置类变量。子类类变量会影响基类类变量,就像往常一样(这 is 继承)。 “所以在这个例子中,类方法没有像我期望的那样改变类变量,而是出现了一个实例变量。”不,检查mytest.epf
  • 顺便说一句,您使用的是完全相反且非常混乱的约定lowercase 用于类,UpperCase 用于实例。请不要这样做,这会使您的代码对习惯使用 Python 的人感到非常困惑,尤其是在您的问题的上下文中,类/实例的区别至关重要
  • @ThierryLathuille 按照要求使代码更小。

标签: python derived-class class-method class-variables


【解决方案1】:

是不是因为c.set_formats使用了cls为实例的类方法?

是的,您可以通过显示相关对象 ID 的打印调用进行检查。

【讨论】:

    猜你喜欢
    • 2011-07-14
    • 1970-01-01
    • 2015-02-04
    • 2019-05-05
    • 2016-01-05
    • 2019-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多