python的类变量和实例变量_python的类变量与实例变量以及__dict__属性

关于Python的实例变量与类变量,先来看一段可能颠覆世界观的例子

1 #!/usr/bin/env python

2 #-*- coding: utf_8 -*-

3 #Date: 2016年10月10日

4 #Author:蔚蓝行

5

6 #首先创建一个类cls,这个类中包含一个值为1的类变量clsvar,一个值为2的实例变量insvar,

7 classcls:8 clsvar = 1

9 def __init__(self):10 self.insvar = 2

11

12 #创建类的实例ins1和ins2

13 ins1 =cls()14 ins2 =cls()15

16 #用实例1为类变量重新赋值并打印

17 print '#'*10

18 ins1.clsvar = 20

19 print cls.clsvar #输出结果为1

20 print ins1.clsvar #输出结果为20

21 print ins2.clsvar #输出结果为1

22

23 #用类名为类变量重新赋值并打印

24 print '#'*10

25 cls.clsvar = 10

26 print cls.clsvar #输出结果为10

27 print ins1.clsvar #输出结果为20

28 print ins2.clsvar #输出结果为10

29

30 #这次直接给实例1没有在类中定义的变量赋值

31 print '#'*10

32 ins1.x = 11

33 print ins1.x #输出结果为11

34

35 #然后再用类名给类中没有定义的变量赋值

36 print '#'*10

37 cls.m = 21

38 print cls.m #输出结果为21

39

40 #再创建一个实例ins3,然后打印一下ins3的变量

41 print '#'*10

42 ins3 =cls()43 print ins3.insvar #输出结果为2

44 print ins3.clsvar #输出结果为10

45 print ins3.m #输出结果为21

46 print ins3.x #报错AttributeError: cls instance has no attribute 'x'

看上去怪怪的,为什么会出现这种结果呢?这就要了解python中的__dict__属性了,__dict__是一个字典,键是属性名,值为属性值。

Python的实例有自己的__dict__,它对应的类也有自己的__dict__ (但是有些特殊的对象是没有__dict__属性的,这里不做讨论)

如果在程序的第15行处加上两句打印语句,打印类和实例1的__dict__属性,将会输出如下:

1 print cls.__dict__

2 print ins1.__dict__

###########输出##########

{'clsvar': 1, '__module__': '__main__', '__doc__': None, '__init__': }

{'insvar': 2}

当打印类的__dict__属性时,列出了类cls所包含的属性,包括一些类内置属性和类变量clsvar以及构造方法__init__

而实例变量则包含在实例对象ins1的__dict__属性中,一个对象的属性查找顺序遵循首先查找实例对象自己,然后是类,接着是类的父类。

现在可以解释开头代码中的神秘现象了,再强调一遍,一个对象的属性查找顺序遵循首先查找实例对象自己,然后是类,接着是类的父类。

在第18行 ins1.clsvar = 20这句后面我们打印一下实例和类的__dict__属性

ins1.clsvar = 20

print ins1.__dict__

print cls.__dict__

###########输出##########

{'insvar': 2, 'clsvar': 20}

{'clsvar': 1, '__module__': '__main__', '__doc__': None, '__init__': }

可以看到,ins1.clsvar = 20这句只是在实例ins1的__dict__属性中增加了'clsvar': 20这一键值对,而类中的clsvar的值并没有改变,重要的事情说三遍:一个对象的属性查找顺序遵循首先查找实例对象自己,然后是类,接着是类的父类。当ins1在自己的__dict__中查找到了clsvar,就不会再向上查找,所以输出了值20。但是此时,cls类中的clsvar的值仍然为1。

但是当在第25行通过类名改变了类的clsvar之后,类的__dict__中的clsvar就被改变成10了,这时打印ins1的clsvar,由于之前第18行的原因,ins1在自己的__dict__中找到了clsvar,就输出了它自己的值20,而ins2自己的__dict__中没有clsvar,就向上查找类的__dict__,并找到了类的clsvar,值为10

第46行的ins3一直向上查找x属性都没有找到,就会抛出AttributeError

像32行和37行这样给类或实例设置属性,其实就是在他们各自的__dict__中添加了该属性,相信现在其他的神秘现象大家也可以自己解释了。

最后附上一个将字典转换成对象的小技巧,如果我们有一个字典如下:

bokeyuan={"b":1,"o":2,"k":3,"e":4,"y":5,"u":6,"a":7,"n":8,

}

现在想将其转换为一个对象,通常会这样写:

1 classDict2Obj:2 def __init__(self,bokeyuan):3 self.b = bokeyuan['b']4 self.o = bokeyuan['o']5 self.k = bokeyuan['k']6 self.e = bokeyuan['e']7 self.y = bokeyuan['y']8 self.u = bokeyuan['u']9 self.a = bokeyuan['a']10 self.n = bokeyuan['n']

但是在了解了__dict__属性之后可以这样写:

1 classDict2Obj:2 def __init__(self,bokeyuan):3 self.__dict__.update(bokeyuan)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值