为什么可以从外部访问类变量

时间:2019-02-06 12:38:40

标签: python oop encapsulation

学习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

谁能告诉我这为什么可行以及它有什么好处?如果我可以从外部更改类中的关键值,那么与将类定义为蓝图并不矛盾,这是否与OOP的{​​{1}}范例冲突。来自encapsulation的我实际上只是知道通过getter和setter访问变量,而不仅仅是这样。所以我很好奇这是允许的重要目的。

1 个答案:

答案 0 :(得分:1)

为什么有可能? Python没有遵循严格的编程范式,这意味着如果在某些情况下有意义的话,解释器就不会妨碍程序员愿意这样做。

话虽这么说,但是这种方法需要程序员方面更高的纪律和责任感,而且还允许其元编程功能具有更大程度的灵活性。

因此,最后这是一个设计选择。这样做的好处是您不需要显式地使用getter / setter。

对于受保护的/私人的成员/方法,习惯上分别在___之前加上前缀。此外,通过方法装饰器@property@.setter,可以伪造一个受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:无法设置属性

当然您仍然可以这样做:

x._an_attribute = 2

x.an_attribute
# 2

EDIT:添加了更多代码以更好地显示用法

编辑:猴子修补中

此外,在您的代码中,您还需要在定义该类之后修改该类,并且所做的更改具有追溯(某种)效果。 这通常称为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

但是,如果有更简洁的选择,那么这当然不是鼓励的编程风格。