【Python】为什么类中的私有属性可以在外部赋值并访问?

Python:为什么类中的私有属性可以在外部赋值并访问?

##问题引入

在慕课网上学习Python类中的私有属性的时候,看到了一个同学的提问:

将count改为__count,为什么实例变量在外部仍然可以修改__count?这里print p1.__count可以打印出100

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,从而实现“私有属性”的特性。但通过“_类名__属性名”也可以访问这些属性。

参考:http://www.pythonclub.org/python-class/private

2、编写测试代码:

以下是在该同学的代码的基础上修改的测试代码:

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
p1 = Person('Bob')
#在实例p1上修改属性值
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上修改属性值
Person.__count_of_class = 'I\'m not the original count_of_class!'
#将这句注释取消掉,会发现真正的私有属性的值也改变了
#Person._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上进行操作,并且分别打印出“__属性名”,以及“_类名__属性名”。

输出结果如下:
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赋值,那么类属性定义的原始值就真正地被覆盖了

"""
取消掉
##Person._Person__count_of_class = 'I\'m not the original count_of_class!'
的注释,输出结果:
"""

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中的都是动态变量)。

以下实例说明可以通过外部赋值来为类创造属性:

class Person(object):
    pass
 
p1=Person()
#给p1创建属性new_of_instance
p1.new_of_instance = 'I\'m new in p1!'
print(p1.new_of_instance)
 
#给Person类创建属性new_of_class
Person.new_of_class = 'I\'m new in Person!'
 
#在类中新加的属性,可以通过实例来访问
print(p1.new_of_class)
 

>>>输出:
I'm new in p1!
I'm new in Person!

问题解决。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值