参考网址

https://blog.csdn.net/weixin_35688430/article/details/108081059

  • "__init__()" 方法不能有返回值,也就是只能是return None

  • 为'类'添加装饰器(本示例中,给'类'动态增加一个属性)


def add_name(name):
    def wrapper(cls):
        cls.name = name
        return cls
    return wrapper 

@add_name('JimGreen')
class Person(object):
    age = 20

p = Person()
print(p.name) # JimGreen

私有属性: 以 '双下划綫' 开头

__age

  • demo 演示
class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.__age = age

    def growup(self, i=1):
        if i > 0 and i < 150: # 控制逻辑
            self.__age += 1

p1 = Person('tom')
p1.growup(20) # 正常的范围
print(p1.__age) # 访问不到

  • 如果访问'私有属性',通过自定义内部方法访问('熟人'走后门)
class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.__age = age

    def growup(self, i=1):
        if i > 0 and i < 150: # 控制逻辑
            self.__age += 1

    def getage(self):
        return self.__age
    
print(Person('tom').getage()) # 18

  • 在外部强行访问'私有变量'也是可以的(不推荐)
class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.__age = age

    def growup(self, i=1):
        if i > 0 and i < 150: # 控制逻辑
            self.__age += 1

    def getage(self):
        return self.__age

p1 = Person('tom')
p1.growup(20) # 正常的范围
# print(p1.__age) # 访问不到

p1.__age = 28 # 设置实例属性
print(p1.__age) # 28

print(p1.getage())  # 19 # 为什么年龄不一样?__age没有覆盖吗?
print(p1.__dict__) # {'name': 'tom', '_Person__age': 19, '__age': 28}
print(p1._Person__age) # 19

p1._Person__age = 15 # 修改私有属性的值
print(p1.getage()) # 15

'''
- 秘密都在 __dict__ 中,里面是 {’__age’: 28, ‘_Person__age’: 38, ‘name’: ‘tom’}

- 私有变量的本质:类定义的时候,如果声明一个实例变量的时候,使用双下划线,Python解释器会将其改名,转换名称为 "_类名__变量名" 的名称,使用原来的名字访问不到

'''


保护变量: 以'单下划线'开头

_age

class Person:
    def __init__(self, name, age=18):
        self.name = name
        self._age = age

p1 = Person('tom')
print(p1._age) # 18
print(p1.__dict__) # {'name': 'tom', '_age': 18}
12345678

'''
- 可以看出,这个_age属性根本就没有改变名称,和普通的属性一样,解释器不做任何特殊处理

- 这只是开发者共同的约定,看见这种变量,就如同私有变量,不要直接使用
'''


私有方法:参考私有属性,类似

class Person:
    def __init__(self, name, age=18):
        self.name = name
        self._age = age


    def _getname(self): # 没改名
        return self.name

    def __getage(self): # 已改名,_Person__getage
        return self._age

tom = Person('tom')
print(tom._getname()) # tom
# print(tom.__getage()) # AttributeError
print(tom.__dict__) # {'name': 'tom', '_age': 18}
print(tom.__class__.__dict__)
print(tom._Person__getage()) # 18


'''
- 单下划线的方法只是开发者之间的约定,解释器不做任何改变

- 双下划线的方法,是私有方法,解释器会改名,改名策略和私有变量相同, _类名__方法名

- 方法变量都在类的 __dict__ 中可以找到。
'''

小结

- 在Python中使用 _单下划线 或者 __ 双下划线来标识一个成员被保护或者被私有化隐藏起来

- 但是,不管使用什么样的访问控制,都不能真正的阻止用户修改类的成员。Python中没有绝对的安全的保护成员 或者私有成员

- 因此,前导的下划线只是一种警告或者提醒,遵守这个约定。除非真有必要,不要修改或者使用保护成员或者私有成员,更不要修改它们。