为了账号安全,请及时绑定邮箱和手机立即绑定

将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


正在回答

3 回答

(刚看到这个问题的时候我也感到很疑惑,下面的回答其实也是我的思考过程,通过测试来一步步获取知识点)

首先要知道一些关于“伪私有属性”的概念:

python的类中通过加双下划线来设置的“私有属性”其实是“伪私有属性”,原理是python编译器将加了双下划线的“__属性名”自动转换成“_类名__属性名”。所以我们在外部用“__属性名”访问私有属性的时候,会触发AttributeError,从而实现“私有属性”的特性。但通过“_类名__属性名”也可以访问这些属性。

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


以下是在你的代码的基础上修改的测试代码:

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!


但是呢,如果不先给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!

希望能够帮到你!

3 回复 有任何疑惑可以回复我~
#1

理Risen

上面的回答可能说的太长了!如果觉得长可以直接看最后一段!!
2018-08-09 回复 有任何疑惑可以回复我~
#2

理Risen

单刀直入版:这是因为给p1.__count赋值的操作,其实是在p1中定义了一个名为__count的变量(因为Python中的都是动态变量)。 十万个为什么版:见完整回答
2018-08-09 回复 有任何疑惑可以回复我~
#3

1小马哥1

p1.__count 是实例的属性,那么实例的属性在外部是不能被修改的呀。为什么p1.__count可以赋值?
2018-09-23 回复 有任何疑惑可以回复我~
#4

qq_疏狂_0

Person.__count_of_class = 'I\'m not the original count_of_class!' print('Person\'s __count_of_class = ',Person.__count_of_class) 你好,就上面的代码,为何倒数第二句可以访问到类的私有属性,如果删去倒数第二句,就出错?
2018-10-26 回复 有任何疑惑可以回复我~
#5

qq_疏狂_0 回复 1小马哥1

还有 Person._Person__count_of_class 和 Person__count_of_class 的不同 你上面说Person__count_of_class 是通过类修改属性值,即 类名__属性名,如果通过实例来修改就应该是 实例名._类名__属性名 ,但这里 类名._类名__属性名 到底是怎么一回事?
2018-10-26 回复 有任何疑惑可以回复我~
查看2条回复

注意看课程的重点,你这样其实是绑定了一个实例属性。而实例属性的优先级要大于类属性https://img1.sycdn.imooc.com//5b7fc86500017aa611480764.jpg

3 回复 有任何疑惑可以回复我~

你试试打印Person._count

p1._count输出的是实例p1的_count值

0 回复 有任何疑惑可以回复我~
#1

慕粉4089541 提问者

这里还是不大能理解,p1.__count=100不是对p1的__count值进行赋值吗?这里不就等于对这个私有属性进行外部访问了么?
2018-08-08 回复 有任何疑惑可以回复我~

举报

0/150
提交
取消
python进阶
  • 参与学习       255665    人
  • 解答问题       2949    个

学习函数式、模块和面向对象编程,掌握Python高级程序设计

进入课程

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

我要回答 关注问题
意见反馈 帮助中心 APP下载
官方微信