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 就会创建一个新的对象。
-
In [7]: a = 1
-
-
In [8]: b = 1
-
-
In [9]: id(a)
-
Out[9]: 140387930888536
-
-
In [10]: id(b)
-
Out[10]: 140387930888536
-
-
In [11]: c = 257
-
-
In [12]: d = 257
-
-
In [13]: id(c)
-
Out[13]: 140387934343656
-
-
In [14]: id(d)
-
Out[14]: 140387934343848