python中不存在只能在对象内部才能访问的私有实例变量,但是有一个预定俗称的习惯,在名称前加一个前导"_"表示API中非公开部分.
因为这种约定对于私有类成员来说是一种有效的用例(避免名称与子类中名称冲突),因此python提供了有限的支持,因此python对该机制提供了有限的支持---称之为名称变形(个人翻译).所有具有指定格式的标识符__spam(至少两个前导"_",最多一个后缀"_")会被文本式的替换为_classname__spam(classname是当前类名),这种变形没有考虑标识符的位置,一旦出现在类中即完成转换
class Test1:
def f1(self):
self.name ="张三"
self.__age = 20 #使用名称变形实现私有变量
print(self.name)
print(self.__age)
class Test2(Test1): #继承基类Test1
def f(self):
print(self.name)
print(self.__age)
inst1 = Test1()
inst1.f1()
Test2.f(inst1)
'''
----------------------
第一次更新2017年4月27日09:27:29
根据上述这一点,个人理解为什么私有属性只能在类内部访问
名称变形规则: __spam会被文本式的替换为_classname__spam,classname是当前类名
1.上述已经解释,为什么不能在其他类中访问,即使把本类实例作为参数传递也是不能访问的
2.关于为什么不能在类外访问?
根据错误提示推测:
1.print(x1.__name)因为__name不是在类内部访问,所以解释器在解析名称__name时,按照普通变量名解析,而不是私有变量
查找顺序: 实例x1的局部命名空间 --> 实例对应类的局部命名空间 --> 基类局部命名空间
2.问题是查找的是__name显然在命名空间中是不存在的
3.print(x1._Test1__name)查找_Test1__name肯定是能找到的
重点来了:
如何实现在类外部访问私有成员(类变量, 类函数)?
1.访问按照名称变化规则文本式的变化后的名称即可
eg:上述print(x1_Test1__name)
----------------------
class Test1:
__name = "张三"
def f1(self):
self.__age = 3
print(self.__name)
print(self.__age)
def f2(self):
print(self.__name)
print(self.__age)
inst1 = Test1()
inst1.f1()
'''
inst1.f2()
'''
print(Test1.__name) # AttributeError: type object 'Test1' has no attribute '__name'
print(Test1.__age) # AttributeError: type object 'Test1' has no attribute '__age'
print(inst1.__name) # AttributeError: 'Test1' object has no attribute '__name'
print(inst1.__age) # AttributeError: 'Test1' object has no attribute '__age'
'''
错误原因:
私有变量只能直接或间接的在类内部访问
'''
第二次更新2017年9月10日11:14:45
1.python中的public --->无前导and尾随下划线
2.python中的protect --->仅一个前导下划线
3.python中的private --->最少两个前导和最多一个尾随下划线
图片较大,右键新窗查看