python的伪私有属性

伪私有属性

类Example中定义的变量__X会自动变成_Example__X, 变量前有双下划线的变量被称为伪私有属性,为什么叫伪私有属性呢?因为该属性并不是私有不可改变的,在类外依旧可以通过 _类名__变量名  来调用修改该属性,那为什么需要伪私有属性的存在呢?先举例一段代码来说明

 1 class C1:
 2     def meth1(self):
 3         self.X=88
 4     def meth2(self):
 5         print(self.X)
 6 
 7 class C2:
 8     def metha(self):
 9         self.X=99
10     def methb(self):
11         print(self.X)
12 
13 class C3(C1,C2):
14     pass
15 
16 I=C3()
17 I.meth1()
18 I.metha()
19 
20 I.meth2()
21 I.methb()
22 print(I.__dict__)
23 
24 I._C1__X=322    #修改伪私有属性
25 print(I.__dict__)
26 
27 # 99
28 # 99
29 # {'X': 99}
30 # {'X': 99, '_C1__X': 322}

假如类1和类2分别由程序员A和B所编写,当两个类混合在一起时,每个类的self.X得到的值取决于最后赋值的类,并不能实现本身的意义(两个程序员对自己分别编写的meth1和metha方法中X的赋值是取不同值,而并非希望类混合后X的取值相同),因而此时若两人使用的是伪私有变量就不会出现这种情况,如下:

 1 class C1:
 2     def meth1(self):
 3         self.__X=88
 4     def meth2(self):
 5         print(self.__X)
 6 
 7 class C2:
 8     def metha(self):
 9         self.__X=99
10     def methb(self):
11         print(self.__X)
12 
13 class C3(C1,C2):
14     pass
15 
16 I=C3()
17 I.meth1()
18 I.metha()
19 
20 I.meth2()
21 I.methb()
22 print(I.__dict__)
23 I._C1__X=322
24 print(I.__dict__)
25 
26 # 88
27 # 99
28 # {'_C2__X': 99, '_C1__X': 88}
29 # {'_C2__X': 99, '_C1__X': 322}

如上避免了实例中潜在的变量名冲突

 

进一步举例

 1 class Super:
 2     def method(self):
 3         print('this is method Super')
 4 
 5 class Tool:
 6     def __method(self):
 7         print('this is method Tool')
 8     def other(self):
 9         print('calling method __method')
10         self.__method()
11 
12 class Sub1(Tool,Super):
13     def actions(self):
14         self.method()
15 
16 class Sub2(Tool):
17     def __init__(self):
18         self.method=99
19         print(self.method)
20 
21 I1=Tool()
22 I1.other()
23 print('************')
24 I2=Sub1()
25 I2.actions()
26 #对类继承树的搜索调用method的顺序本是在Tool类中搜索再在类Super中搜索
27 #但因类Tool类中method为伪私有方法并不能在Tool类外调用,因而Tool类中method方法被隐藏
28 #再到类Super中搜索,因Super类中method方法未私有化,而调用了Super类中method方法
29 print('-----------------')
30 I2.other() #继承树中搜索other方法并未被Tool类私有化,从而能通过类中other方法调用私有方法__method
31 print('***************')
32 I3=Sub2()
33 #实例化Sub2方法已不再是对父类Tool中method方法的重写,而是创建一新成员变量method
34 
35 # calling method __method
36 # this is method Tool
37 # ************
38 # this is method Super
39 # -----------------
40 # calling method __method
41 # this is method Tool
42 # ***************
43 # 99

 

“单下划线” 开始的成员变量叫做保护变量,意思是只有类对象和子类对象自己能访问到这些变量,不能直接访问的类属性,需通过类提供的接口进行访问,不能用“from xxx import *”而导入;
“双下划线” 开始的是私有成员,意思是只有类对象自己能访问连子类对象也不能访问到这个数据

 

 

转载于CS实验室的大佬猫的  

https://mp.weixin.qq.com/s?__biz=MzIzNTU1MjIxMQ==&mid=2247483658&idx=1&sn=e75ca0f76cfd3be5c94518be572c2dce&chksm=e8e42db6df93a4a047ea2539acca737d2c3a98061fd4233a1dc4f5b5d32480569615f524c9b8&mpshare=1&scene=23&srcid=0710BO36kCHKbkggf8LdxyNh#rd

 

 1 class Father:
 2     sex="male"
 3 
 4     def __init__(self,name,age,money=[]):
 5         self._name=name
 6         self.__age=age
 7         self.money=money
 8 
 9 class Sun(Father):
10     def __init__(self,name,age):
11         super(Sun,self).__init__(name,age)
12 
13 
14 if __name__=="__main__":
15     f=Father("f_name",23)
16     s=Sun("s_name",3)
17     print("father's default money:{}".format(f.money))
18     f.money.append(100)
19     print("father put 100 in money:{}".format(f.money))
20     print("sun's default money:{}".format(s.money))
21     s.money.append(10)
22     print("sun put 10 in money:{}".format(s.money))
23     print("now,father's money:{}".format(f.money))
24 
25     print(Father.__init__.__defaults__[0] is f.money)
26     print(f._name is s._name)
27     print(f._Father__age)
28     print(s._Father__age)
29     print(f._Father__age is s._Father__age)
30     print(f.money is s.money)

 

默认值 money=[] 在定义函数时计算(通常在加载模块时),因此默认值变成了函数对象的属性,从而修改父类的money会直接影响到子类的money

 

Python 有个驻留机制,即共享字符串字面量,是一种优化措施,防止重复创建热门数字。但 CPython 不会驻留所有字符串和整数,驻留的条件是实现细节,而且没有文档说明。

字符串驻留的范围: 0 ~ 9A ~ Z_a ~ z
整数的驻留范围: -5 ~ 256 。
如果字符串或整数不在上述范围,Python 就会创建一个新的对象。

  1. In [7]: a = 1

  2.  

  3. In [8]: b = 1

  4.  

  5. In [9]: id(a)

  6. Out[9]: 140387930888536

  7.  

  8. In [10]: id(b)

  9. Out[10]: 140387930888536

  10.  

  11. In [11]: c = 257

  12.  

  13. In [12]: d = 257

  14.  

  15. In [13]: id(c)

  16. Out[13]: 140387934343656

  17.  

  18. In [14]: id(d)

  19. Out[14]: 140387934343848

 

posted @ 2018-03-24 21:14  xajh00789  阅读(399)  评论(0编辑  收藏  举报