Python的实例变量和类变量的区别

正好在写 scrapy 爬虫时看到了,在这里记录一下。

类变量的概念:

类变量就是定义在类中,但是在函数体之外的变量,通常不使用 self 加变量名赋值。类变量在所有实例中都是可以直接访问的,所有实例共享类变量。

实例变量的概念:

实例变量是定义在方法中的变量,就是用 self 绑定在实例上的对象,每个实例的实例变量都可能是不同的。

类变量和实例变量的访问方式:
  • 不论是在类的内部还是外部,都可以用类名 . 变量名的方式去访问类变量。在类的内部,也可以用 self. 变量名的方式来访问,但是这样的话这个类变量已经成了一个实例变量,实例变量是可以被重新赋值的,就像局部变量会屏蔽全局变量一样,self. 变量名的方式访问类变量可能会访问到错误的值。所以不推荐用这种方式来访问类变量。

  • 在每个类的内部,可以通过 self. 变量名的形式来访问实例变量,在类的外部,可以通过实例名 . 变量名的方式来访问实例变量。实例变量是绑定在一个实例上的变量,它只能用 self. 变量名的方式来访问。

来验证一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# -*- coding: utf-8 -*-
class demo(object):
# 定义一个类变量
class_var = 10

def foo(self):
# 通过类名.变量名的方式访问类变量
print('demo.class_var ->' + demo.class_var.__str__())
# 通过self.变量名的方式访问类变量
print('self.class_var ->' + self.class_var.__str__())

# 通过self.变量名的方式来修改类变量
self.class_var = 40
# 输出结果
print('self.class_var = 40 -> demo.class_var' + demo.class_var.__str__())
print('self.class_var = 40 -> self.class_var' + self.class_var.__str__())

# 在函数内部改变类变量的值
class_var = 20
print('class_var = 20 -> class_var ->' + class_var.__str__())

# 通过类名.变量名的方式改变类变量的值
demo.class_var = 15
print('demo.class_var = 15 -> demo.class_var' + demo.class_var.__str__())
print('demo.class_var = 15 -> self.class_var' + self.class_var.__str__())


# 创建两个实例,第一个实例中的foo函数进行了一系列操作
obj1 = demo()
obj2 = demo()
obj1.foo()
# 进行了一系列操作之后显示各个变量的值
print('demo.class_var ->' + demo.class_var.__str__())
print('obj1.class_var ->' + obj1.class_var.__str__())
print('obj2.class_var ->' + obj2.class_var.__str__())

来看一下程序运行的输入:

1
2
3
4
5
6
7
8
9
10
demo.class_var ->10
self.class_var ->10
self.class_var = 40 -> demo.class_var10
self.class_var = 40 -> self.class_var40
class_var = 20 -> class_var ->20
demo.class_var = 15 -> demo.class_var15
demo.class_var = 15 -> self.class_var40
demo.class_var ->15
obj1.class_var ->40
obj2class_var ->15

通过上面的程序输出可以看出:

  • 通过 self. 变量名的方式和类 . 变量名的方式都可以访问类变量。
  • 通过 self. 的方式改变了类变量的值,这个变量就被绑定在了实例上,成了一个实例变量,但是类变量的值没有受到影响。
  • 在函数中直接改变类变量的值,因为累变量是所有实例共享的,所以所有的实例再次访问类变量时都会访问到已经改变的变量的值。
  • 通过类名 . 变量名的方式改变类变量的值不影响实例变量的值。
  • 通过最后的三个输出可以看出,类变量的值已经被更改为 15,实例变量的值已经被更改为 40(屏蔽了类变量的值),obj2 没有运行 foo 函数,但是通过实例 . 类变量去访问类变量,可以看到返回的值是已经被更改过的类变量的值,由此可知类变量是所有实例共享的。

参考资料:

https://www.jianshu.com/p/9fefb52ca91b

http://kuanghy.github.io/2015/12/19/python-variable

本文章首发于个人博客 LLLibra146’s blog
本文作者:LLLibra146
版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!
本文链接https://blog.d77.xyz/archives/6c4a1a65.html