【发布时间】: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