Python 如何防止类属性从类外修改

Python 如何防止类属性从类外修改,python,oop,getter-setter,private-members,Python,Oop,Getter Setter,Private Members,在下面的示例中,我的目标是防止从类资产之外修改位置属性。我通过创建setter方法实现了这一点。因此,从外部调用cash.position=1000会导致错误 问题是:如果我在课外打电话给cash.\u position=1000,我仍然可以修改它 class Asset: def __init__(self, start=0): self._position = start # Getter @property def position(se

在下面的示例中,我的目标是防止从类
资产
之外修改
位置
属性。我通过创建setter方法实现了这一点。因此,从外部调用
cash.position=1000
会导致错误

问题是:如果我在课外打电话给cash.\u position=1000,我仍然可以修改它

class Asset:

    def __init__(self, start=0):
        self._position = start

    # Getter
    @property
    def position(self):
        print("property class method called")
        print("position = {}".format(self._position))
        return self._position

    # Setter
    @position.setter
    def __position(self, value): # Private method - can't be accessed from outside class
        print("@position.setter method called")
        self._position = value

    def transact(self, value):
        print("transact method called")
        self._position = self.position + value

cash = Asset(start=50)
cash.position

cash = Asset()
print(cash.position)
cash.transact(30)
print(cash.position)
cash.transact(-60)
print(cash.position)
cash.position = 1000 # OK - does not allow to change position
cash._position = 1000 # Problem - does allow to change position
cash.position

不幸的是,python并没有真正的概念。在变量名前面加上
\uuuuuu
实际上是指示python使用该名称,即用
\u classname\uuuuuuu varname
替换它。这在子类化时非常有用。 在变量名前面加上
(一个下划线)是识别用户认为私有的变量的常规方法。理论上,这已经足够作为一个访问修饰符了,因为用户被正确地警告,弄乱这些值将破坏封装

然而,有一种相当好的方法来实现您可能想要的行为,它是通过使用
属性
装饰器()。考虑这个代码:

class C:
    def __init__(self, temperature):
        self.temperature = temperature

    @property
    def temperature(self):
        print("GET")
        return self.__temperature

    @temperature.setter
    def temperature(self, value):
        print("SET")
        self.__temperature = value

c = C(10)
print(c.temperature)
输出:

SET
GET
10

如果不想提供对基础属性的公共访问,请保持setter未定义。如果您愿意,您可以使用
\u position
而不是
\u position
,但即使这样也不能保证防止有人更改它的价值:您可以使用
现金来执行此操作。\资产\u position=…

class Asset:

    def __init__(self, start=0):
        self._position = start

    @property
    def position(self):
        return self._position

    def transact(self, value):
        self._position = self.position + value
        # or
        # self._position += value

Python没有私有变量。