1:伪私有属性介绍
在Python中一切都是对象,并且类的所有属性和方法都是公有的(public),并不存在private 关键字来声明私有方法或属性。那么在Python中怎么实现像其他编程语言一样的私有属性呢?其实只需在属性前加上双下划线(但是结尾处不能有双下划线)即可,如:self.__name,这并不是真正私有,而是“伪私有”,因为Python会把self.__name 变为self._类名__name,你可以使用"对象._类名__name"访问这个属性。
# encoding=gbk class Test: def __init__(self,name): self.__name = name t = Test('ixusy88')print(t.__dict__) # 输出 {'_Test__name': 'ixusy88'};属性 __name 变为 _Test__name了# print(t.__name) # 输出:AttributeError: 'Test' object has no attribute '__name'; # 不能访问属性__name,因为属性 __name 变为 _Test__name了,不存在属性__name # 可以通过 对象._类名__属性 访问print(t._Test__name)# 通过下标访问print(t.__dict__['_Test__name'])
2:双下划线:伪私有属性实现过程
在运算符重载中有提到 __setattr__ 能够拦截所有的属性赋值操作,__getattr__能够拦截没有定义属性的访问(即不存在于
__dict__中的属性)。
其拦截过程如下:
self.属性 = 属性值 会调用 self.__setattr__('属性',属性值)
self.属性 = 属性值 会调用 self.__setattr__('_类__属性',属性值)
对象.属性 = 属性值 会调用 self.__setattr__('属性',属性值)
对象.属性 = 属性值 会调用 self.__setattr__('属性',属性值)
只拦截不处理:
# encoding=gbk class Test: def __init__(self,name,age): self.__name = name # self.__setattr__('_Test__name',name) self.age = age # self.__setattr__('age',age) def __getattr__(self, item): print('in __getattr__:' + item) def __setattr__(self, key, value): print('in __setattr__:' + key,value) def setV(self): self.__a1 = 'a1_11' # self.__setattr__('_Test__a1','a1_11') print('1:' + '*'*30)t = Test('ixusy88',18)print('2:' + '*'*30)print(t.__dict__) # 输出 {} ,因为在__setattr__中拦截了所有的属性赋值,print('3:' + '*'*30)t.setV()print('4:' + '*'*30)t.aa = '123' # self.__setattr__('aa','123')print('5:' + '*'*30)t.__bb = '123' # self.__setattr__('__bb','123')print('6:' + '*'*30)print(t.vv) # self.__getattr__('vv')print('7:' + '*'*30)print(t.age) # self.__getattr__('age') , 在构造函数中虽然有self.age 赋值,但是__getattr__会拦截所有,print('8:' + '*'*30)print(t.__dict__) # 输出 {} ,因为在__setattr__中拦截了所有的属性赋值, """输出结果:1:******************************in __setattr__:_Test__name ixusy88in __setattr__:age 182:******************************{}3:******************************in __setattr__:_Test__a1 a1_114:******************************in __setattr__:aa 1235:******************************in __setattr__:__bb 1236:******************************in __getattr__:vvNone7:******************************in __getattr__:ageNone8:******************************{}"""
正常拦截:
# encoding=gbk class Test: def __init__(self,name,age): self.__name = name # self.__setattr__('_Test__name',name) self.age = age # self.__setattr__('age',age) def __getattr__(self, item): print('in __getattr__:' + item) # raise TypeError('private attribute:' + item) # 抛出异常 def __setattr__(self, key, value): print('in __setattr__:' + key,value) self.__dict__[key] = value def setV(self): self.__a1 = 'a1_11' # self.__setattr__('_Test__a1','a1_11') print('1:' + '*'*30)t = Test('ixusy88',18)print('2:' + '*'*30)print(t.__dict__) # 输出 {'_Test__name': 'ixusy88', 'age': 18}print('3:' + '*'*30)t.setV()print('4:' + '*'*30)t.aa = '123' # self.__setattr__('aa','123')print('5:' + '*'*30)t.__bb = '123' # self.__setattr__('__bb','123')print('6:' + '*'*30)print(t.vv) # self.__getattr__('vv')print('7:' + '*'*30)print(t.age) # 直接输出 18,不会调用self.__getattr__('age') ,print('8:' + '*'*30)print(t.__dict__) # 输出 {'_Test__name': 'ixusy88', 'age': 18, '_Test__a1': 'a1_11', 'aa': '123', '__bb': '123'} """输出:1:******************************in __setattr__:_Test__name ixusy88in __setattr__:age 182:******************************{'_Test__name': 'ixusy88', 'age': 18}3:******************************in __setattr__:_Test__a1 a1_114:******************************in __setattr__:aa 1235:******************************in __setattr__:__bb 1236:******************************in __getattr__:vvNone7:******************************188:******************************{'_Test__name': 'ixusy88', 'age': 18, '_Test__a1': 'a1_11', 'aa': '123', '__bb': '123'}"""