Python:为什么类中的私有属性可以在外部赋值并访问?
问题引入
在慕课网上学习Python**类中的私有属性**的时候,看到了一个同学的提问:
将count改为__count,为什么实例变量在外部仍然可以修改__count?这里print p1.__count可以打印出100
1
2
3
4
5
6
7
8
9
10
11
12
|
class Person( object ):
__count = 0
def __init__( self , name):
Person.__count = Person.__count + 1
self .name = name
print Person.__count
p1 = Person( 'Bob' )
p1.__count = 100
print p1.__count
p2 = Person( 'Alice' )
print Person.__count
|
问题解决:
单刀直入版:
这是因为给p1.__count赋值的操作,其实是在p1中定义了一个名为__count的变量(因为Python中的都是动态变量),而没有改变类中真正的属性。
太长但还是要看看版:
知识点清单:
1、类的“伪私有属性”
2、在类的外部动态地创建类属性
问题解决过程:
1、“伪私有属性”的概念:
python的类中通过加双下划线来设置的“私有属性”其实是“伪私有属性”,原理是python编译器将加了双下划线的“属性名”自动转换成“类名属性名”。所以我们在外部用“属性名”访问私有属性的时候,会触发AttributeError,从而实现“私有属性”的特性。但通过“类名属性名”也可以访问这些属性。
参考:
2、编写测试代码:
以下是在该同学的代码的基础上修改的测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Person( object ):
__count_of_class = 'original count_of_class'
def __init__( self , name):
self .name = name
print ( 'in class Person : count_of_class = ' , Person.__count_of_class, '\n' )
p1 = Person( 'Bob' )
p1.__count_of_class = 'I\'m not the original count_of_class!'
print ( 'p1\'s _Person__count_of_class = ' ,p1._Person__count_of_class)
print ( 'p1\'s __count_of_class = ' ,p1.__count_of_class, '\n' )
Person.__count_of_class = 'I\'m not the original count_of_class!'
print ( 'Person\'s _Person__count_of_class = ' ,Person._Person__count_of_class)
print ( 'Person\'s __count_of_class = ' ,Person.__count_of_class)
|
分别在实例p1上和类Person上进行操作,并且分别打印出“__属性名”,以及“_类名__属性名”。
输出结果如下:
1
2
3
4
5
6
7
|
in class Person : count_of_class = original count_of_class
p1's _Person__count_of_class = original count_of_class
p1 's __count_of_class = I' m not the original count_of_class!
Person's _Person__count_of_class = original count_of_class
Person 's __count_of_class = I' m not the original count_of_class!
|
**由此可见,虽然用p1.__count_of_class给它赋值了,但其实在类中真正的属性_Person__count_of_class的原始值是没有改变的。
但是如果将p1._Person__count_of_class赋值,那么类属性定义的原始值就真正地被覆盖了**
1
2
3
4
5
6
7
8
9
10
11
12
13
|
in class Person : count_of_class = original count_of_class
p1's _Person__count_of_class = original count_of_class
p1 's __count_of_class = I' m not the original count_of_class!
Person 's _Person__count_of_class = I' m not the original count_of_class!
Person 's __count_of_class = I' m not the original count_of_class!
|
由此,我们知道了:_count_of_class和_Person_count_of_class不是同一个东西。
最后的问题
但是呢,如果不先给p1.__count_of_class赋值,直接打印它又会触发AttributeError,这是为什么?
这是因为给p1.__count_of_class赋值的操作,其实是在p1中定义了一个名为__count_of_class的变量(因为Python中的都是动态变量)。
以下实例说明可以通过外部赋值来为类创造属性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Person( object ):
pass
p1 = Person()
p1.new_of_instance = 'I\'m new in p1!'
print (p1.new_of_instance)
Person.new_of_class = 'I\'m new in Person!'
print (p1.new_of_class)
>>>输出:
I'm new in p1!
I'm new in Person!
|
问题解决。
|