code1
class Foo(object):
x = 1.5
foo = Foo()
print Foo.x # 值为 1.5 类属性
print foo.x # 值为 1.5 ,实例属性(在实例属性没有的情况下,使用类属性)
foo.x = 1.7
print foo.x # 实例属性
print Foo.x # 实例属性的修改不会影响类属性(实例属性可以有效屏蔽类属性)
code2
#!/usr/bin/env python
# coding=utf-8
class Foo(object):
x = {1: 'hello'}
foo = Foo()
print foo.x # 值为{1: 'hello'}
print Foo.x # 值为{1: 'hello'}
foo.x[1] = 'world'
print foo.x # 值为{1: 'world'}
print Foo.x # 值为{1: 'world'}
问题: 为什么第一个代码段当类属性是不可变对象时(数字),修改实例属性,不会影响到类属性 而第二个代码段中,当类属性是可变对象时(字典),修改实例属性,导致类属性也改变了?
1
justou 2016-11-09 19:51:56 +08:00
这儿跟可变对象和不可变对象没啥关系;
类属性被所有实例共享, 实例都是从某个类(相当于模板)造出来的; 实例属性可各不相同, 还可以动态添加删除 这里是 foo.x=1.7 这种赋值方式的问题, 这会给实例动态添加一个(实例)属性 x, 跟类属性 x 不同 比如 print foo.y 会抛出 AttributeError, 但 foo.y=1 会动态添加一个实例属性 y 修改类属性用类名访问 Foo.x=2, 所有实例读取 x 属性时都是一样的值.(前提是没有被实例属性覆盖) class Cls(object): x = 1 c1 = Cls() c2 = Cls() print c1.x # 1 print c2.x # 1 Cls.x = 2 print c1.x # 2 print c2.x # 2 c1.x = 233 print c1.x # 233, 先得到实例属性 print c2.x # 2 print Cls.x # 2 |
2
justou 2016-11-09 19:56:58 +08:00 1
实例属性跟类属性是放在不同的字典里面的, print c1.x, c1.x = 233 这种操作就是字典操作
print c1.__dict__ print Cls.__dict__ |
3
blackeeper 2016-11-09 20:23:35 +08:00
楼上说的很对,实例属性跟类属性是放在不同的字典里面的。
foo 实例有两个字典: 1 、实例的字典 foo.__dict__ 2 、类的字典 foo.__class__.__dict__ |
4
wisefree 2016-11-09 20:43:49 +08:00
'''python
#coding:utf-8 class Foo(object): x = {1:'hello'} foo = Foo() foo.x[1] = 'world' print(foo.__dict__) ''' 输出: {} 说明, foo.x[1] = 'world',根本没有创建一个实例属性 |
5
bomb77 2016-11-09 20:44:27 +08:00
@justou
所以说楼主 code2 代码现象的原因是: foo.x[1] = 'world' ,因为 foo 实例本身没有实例属性 x ,且没有 x[1] = 'world' 创建变量的语法,所以 foo.x[1] = 'world' 修改了类属性 Foo.x 不知是不是这么理解? |
6
wisefree 2016-11-09 20:45:16 +08:00
继续引发一点思考
```python #coding:utf-8 class Foo(object): x = {1:'hello'} foo = Foo() foo.x = {1:'world'} print(foo.x) print(Foo.x) ``` 输出: {1: 'world'} {1: 'hello'} |
7
Contextualist 2016-11-09 21:18:55 +08:00 via iPad 2
我感觉上面各位都有些偏题了,造成这个现象的原因的确如楼主所说:字典是可变对象。
首先“实例属性的修改不会影响类属性”的确是对的 在实例属性没有的情况下,使用类属性,所以实例与类的 x 都是对那个字典的引用 但是 code2 中 foo.x[1] = 'world' 根本就**没有**修改或者创建实例属性,是 foo.x 的引用那个字典里的值被改变了, foo.x 的引用没变。然后因为实例与类的 x 都是对那个字典的引用,所以值相同 |
8
Tianny OP @blackeeper 感谢!
|