Python封装通过损坏工作,但混淆了从类外对属性的赋值

2024-04-19 13:33:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我不知道这里发生了什么事。 我创建了我的类,使用双下划线来破坏名称,这样它就可以作为一种封装方式,我创建了一个对象的实例,我得到了访问它们的方法,然后我尝试从类外部设置它们,看起来python没有试图修改属性,而是在创建新的变量,在对象的外部,与对象的属性具有相同的名称。你知道吗

是这样吗?如果不是,什么?你知道吗

class Person:
    def __init__(self, __name, __position):
    self.__name = __name
    self.__position = __position

    def talk(self, aStatement):
        print(aStatement)
    def walk(self, aPosition):
        self.__position = aPosition
    def getPosition(self):
        return self.__position
    def getName(self):
        return self.__name

person1 = Person("Mr. Table", ["Room 115", [13, 20]])
print(person1.getPosition())
person1.walk(["Room 117", [0, 0]])
print(person1.getPosition())
person1.name = "Pedro"
person1.position = ["Room XXX", [13, 20]]
print(person1.name)
print(person1.getName())
print(person1.position)
print(person1.getPosition())

Tags: 对象nameself名称属性defpositionperson
2条回答

Python的名称损坏非常简单,当在Person类中使用时,它将self.__name转换成self.__Person_name(当在其他类中使用时,它使用其他类的名称而不是Person)。你知道吗

名称损坏旨在帮助您避免意外的名称冲突,特别是对于不能预先知道其实例上将存在哪些其他属性的mixin类。你知道吗

它并不真正用于封装或使变量“私有”。Python的设计者通常认为这不是很有用。避免其他程序员以错误的方式使用您的类的方法是很好地记录您的代码,而不是声明私有的东西,或者跳过一堆限制来锁定它们。你知道吗

如果确实要控制对类上属性的访问,请考虑使用property(控制对单个属性的分配)或__setattr__(控制对类的所有属性的分配)。通常情况下,虽然没有必要阻止属性分配,但只要文档清楚地说明哪些属性是公共API的一部分(以及每个属性可以接受哪些值)。如果您发现在使用API之后需要验证特定属性的值,那么您仍然可以返回并在实际使用之后将其转换为property。(无法重构属性访问是其他语言如C++和java倾向于说,你应该总是使用GETER和SETER方法的主要原因。)

默认情况下,Python实例的后台存储是dictionary,它可以像well dictionary一样进行操作。您可以获取或设置所需的任何属性并添加新属性。要限制所有人的免费访问,可以使用decorators指定访问者:

class Person:
    def __init__(self, name, position):
        self.__name = name
        self.__position = position

    @property
    def name(self):
        return self.__name

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

    @position.setter
    def position(self, aPosition):
        self.__position = aPosition

person1 = Person("Mr. Table", ["Room 115", [13, 20]])
print(person1.position)
person1.position = ["Room 117", [0, 0]]
print(person1.position)
person1.name = "Pedro"  # this will crash the code as it's "readonly"
person1.position = ["Room XXX", [13, 20]]
print(person1.name)
print(person1.position)

虽然我们期望访问器person1.position(),但现在它是person1.person,可以进行计算或设置。decorator函数为你设置了这个。它看起来像一个简单的属性,但实际上它背后有代码。因为我们没有为“name”包含setter,所以您可以通过person1.name访问它,但是您不能这样设置。你知道吗

您可能会读到__slots__,并试图使用它来限制对底层备份存储的访问。这个特性实际上只是为了节省具有大量实例的类的空间,而试图用它来约束对象的行为只会导致撕裂。你知道吗

相关问题 更多 >