为什么 class 变量可以从外部访问
Why is a class variable accessable from outside
学习中Python 刚刚遇到一些不太懂的东西。让我们举个例子:
class CV_Test:
classVar = 'First'
cv = CV_Test()
print(cv.classVar)
CV_Test.classVar = 'Second'
cv2 = CV_Test()
print(cv2.classVar)
print(CV_Test.classVar)
输出:
First
Second
Second
谁能告诉我为什么这是可能的,它有什么好处?如果我可以从外部更改 class 中的关键值,这是否与将 class 定义为蓝图相矛盾,这是否与 [=14] 的 OOP
范式冲突=].来自 .NET
我实际上只知道通过 getter 和 setter 访问变量但不只是这样。所以我很好奇允许这样做的重要目的是什么。
为什么可能? Python 不遵循限制性编程范式,这意味着如果某件事在某些情况下有意义,解释器不应妨碍程序员愿意这样做。
话虽这么说,这种方法要求程序员方面有更高水平的纪律和责任,但也允许其元编程功能具有更大程度的灵活性。
所以,这最终是一种设计选择。它的优点是你不需要明确地必须使用 getters/setters.
对于protected/private members/methods,习惯上分别加上_
或__
。此外,可以通过方法装饰器 @property
和 [=19] 伪造 getter/setter 受保护的行为(这也将允许执行其他代码) =],例如:
class MyClass():
_an_attribute = False
@property
def an_attribute(self):
return self._an_attribute
@an_attribute.setter
def an_attribute(self, value):
self._an_attribute = value
可以这样使用:
x = MyClass()
x.an_attribute
# False
x.an_attribute = 1
# sets the internal `_an_attribute` to 1.
x.an_attribute
# 1
你可以省略 @an_attribute.setter
部分,如果你想要 只读 (有点)属性,那么下面的代码:
x = MyClass()
x.an_attribute
# False
但是,尝试更改其值会导致:
x.an_attribute = 1
AttributeError: can't set attribute
当然你还可以:
x._an_attribute = 2
x.an_attribute
# 2
(编辑:添加了更多代码以更好地显示用法)
编辑:关于猴子补丁
此外,在您的代码中,您还修改了 class 的定义,并且这些更改具有追溯(某种)效果。
这通常称为 monkey patching 并且在某些情况下再次有用,您希望在代码的某些部分触发特定行为同时保留其大部分逻辑,例如:
class Number():
value = '0'
def numerify(self):
return float(self.value)
x = Number()
x.numerify()
# 0.0
Number.numerify = lambda self: int(self.value)
x.numerify()
# 0
但如果有更简洁的选项可用,这肯定不是一种鼓励的编程风格。
学习中Python 刚刚遇到一些不太懂的东西。让我们举个例子:
class CV_Test:
classVar = 'First'
cv = CV_Test()
print(cv.classVar)
CV_Test.classVar = 'Second'
cv2 = CV_Test()
print(cv2.classVar)
print(CV_Test.classVar)
输出:
First
Second
Second
谁能告诉我为什么这是可能的,它有什么好处?如果我可以从外部更改 class 中的关键值,这是否与将 class 定义为蓝图相矛盾,这是否与 [=14] 的 OOP
范式冲突=].来自 .NET
我实际上只知道通过 getter 和 setter 访问变量但不只是这样。所以我很好奇允许这样做的重要目的是什么。
为什么可能? Python 不遵循限制性编程范式,这意味着如果某件事在某些情况下有意义,解释器不应妨碍程序员愿意这样做。
话虽这么说,这种方法要求程序员方面有更高水平的纪律和责任,但也允许其元编程功能具有更大程度的灵活性。
所以,这最终是一种设计选择。它的优点是你不需要明确地必须使用 getters/setters.
对于protected/private members/methods,习惯上分别加上_
或__
。此外,可以通过方法装饰器 @property
和 [=19] 伪造 getter/setter 受保护的行为(这也将允许执行其他代码) =],例如:
class MyClass():
_an_attribute = False
@property
def an_attribute(self):
return self._an_attribute
@an_attribute.setter
def an_attribute(self, value):
self._an_attribute = value
可以这样使用:
x = MyClass()
x.an_attribute
# False
x.an_attribute = 1
# sets the internal `_an_attribute` to 1.
x.an_attribute
# 1
你可以省略 @an_attribute.setter
部分,如果你想要 只读 (有点)属性,那么下面的代码:
x = MyClass()
x.an_attribute
# False
但是,尝试更改其值会导致:
x.an_attribute = 1
AttributeError: can't set attribute
当然你还可以:
x._an_attribute = 2
x.an_attribute
# 2
(编辑:添加了更多代码以更好地显示用法)
编辑:关于猴子补丁
此外,在您的代码中,您还修改了 class 的定义,并且这些更改具有追溯(某种)效果。 这通常称为 monkey patching 并且在某些情况下再次有用,您希望在代码的某些部分触发特定行为同时保留其大部分逻辑,例如:
class Number():
value = '0'
def numerify(self):
return float(self.value)
x = Number()
x.numerify()
# 0.0
Number.numerify = lambda self: int(self.value)
x.numerify()
# 0
但如果有更简洁的选项可用,这肯定不是一种鼓励的编程风格。