Python类变量和实例变量(类属性和实例属性)
⽆论是类属性还是类⽅法,都⽆法向普通变量或者函数那样,在类的外部直接使⽤它们。我们可以将类看做⼀个独⽴的空间,则类属性其实就是在类体中定义的变量,类⽅法是在类体中定义的函数。
前⾯章节提到过,在类体中,根据变量定义的位置不同,以及定义的⽅式不同,类属性⼜可细分为以下 3 种类型:
1. 类体中、所有函数之外:此范围定义的变量,称为类属性或类变量;
2. 类体中,所以函数内部:以“self.变量名”的⽅式定义的变量,称为实例属性或实例变量;
3. 类体中,所有函数内部:以“变量名=变量值”的⽅式定义的变量,称为局部变量。
不仅如此,类⽅法也可细分为实例⽅法、静态⽅法和类⽅法,后续章节会做详细介绍。
那么,类变量、实例变量以及局部变量之间有哪些不同呢?接下来就围绕此问题做详细地讲解。
类变量(类属性)
类变量指的是在类中,但在各个类⽅法外定义的变量。举个例⼦:
1. class CLanguage :
2. # 下⾯定义了2个类变量
3. name = "C语⾔中⽂⽹"
4. add = "c.biancheng"
5. # 下⾯定义了⼀个say实例⽅法
6. def say(self, content):
7. print(content)
上⾯程序中,name 和 add 就属于类变量。
类变量的特点是,所有类的实例化对象都同时共享类变量,也就是说,类变量在所有实例化对象中是作为公⽤资源存在的。类⽅法的调⽤⽅式有 2 种,既可以使⽤类名直接调⽤,也可以使⽤类的实例化对象调⽤。实例化类和实例化对象
⽐如,在 CLanguage 类的外部,添加如下代码:
1. #使⽤类名直接调⽤
2. print(CLanguage.name)
3. print(CLanguage.add)
4. #修改类变量的值
5. CLanguage.name = "教程"
6. CLanguage.add = "c.biancheng/python"
7. print(CLanguage.name)
8. print(CLanguage.add)
程序运⾏结果为:
可以看到,通过类名不仅可以调⽤类变量,也可以修改它的值。
当然,也可以使⽤类对象来调⽤所属类中的类变量(此⽅式不推荐使⽤,原因后续会讲)。例如,在 CLanguage 类的外部,添加如下代码:
1. clang = CLanguage()
2. print(clang.name)
3. print(clang.add)
运⾏程序,结果为:
注意,因为类变量为所有实例化对象共有,通过类名修改类变量的值,会影响所有的实例化对象。例如,在 CLanguage 类体外部,添加如下代码:
1. print("修改前,各类对象中类变量的值:")
2. clang1 = CLanguage()
3. print(clang1.name)
4. print(clang1.add)
5. clang2 = CLanguage()
9. print("修改后,各类对象中类变量的值:")
10. CLanguage.name = "Python教程"
11. CLanguage.add = "c.biancheng/python"
12. print(clang1.name)
13. print(clang1.add)
14. print(clang2.name)
15. print(clang2.add)
程序运⾏结果为:
显然,通过类名修改类变量,会作⽤到所有的实例化对象(例如这⾥的 clang1 和 clang2)。
注意,通过类对象是⽆法修改类变量的。通过类对象对类变量赋值,其本质将不再是修改类变量的值,⽽是在给该对象定义新的实例变量(在讲实例变量时会进⾏详细介绍)。
值得⼀提的是,除了可以通过类名访问类变量之外,还可以动态地为类和对象添加类变量。例如,在 CLanguage 类的基础上,添加以下代码:
1. clang = CLanguage()
2. CLanguage.catalog = 13
3. print(clang.catalog)
运⾏结果为:
13
实例变量(实例属性)
实例变量指的是在任意类⽅法内部,以“self.变量名”的⽅式定义的变量,其特点是只作⽤于调⽤⽅法的对象。另外,实例变量只能通过对象名访问,⽆法通过类名访问。
举个例⼦:
1. class CLanguage :
2. def __init__(self):
3. self.name = "C语⾔中⽂⽹"
4. self.add = "c.biancheng"
5. # 下⾯定义了⼀个say实例⽅法
6. def say(self):
7. self.catalog = 13
此 CLanguage 类中,name、add 以及 catalog 都是实例变量。其中,由于 __init__() 函数在创建类对象时会⾃动调⽤,⽽ say() ⽅法需要类对象⼿动调⽤。因此,CLanguage 类的类对象都会包含 name 和 add 实例变量,⽽只有调⽤了 say() ⽅法的类对象,才包含 catalog 实例变量。
例如,在上⾯代码的基础上,添加如下语句:
1. clang = CLanguage()
2. print(clang.name)
3. print(clang.add)
4. #由于 clang 对象未调⽤ say() ⽅法,因此其没有 catalog 变量,下⾯这⾏代码会报错
5. #print(clang.catalog)
6.
7. clang2 = CLanguage()
8. print(clang2.name)
9. print(clang2.add)
10. #只有调⽤ say(),才会拥有 catalog 实例变量
11. clang2.say()
12. print(clang2.catalog)
运⾏结果为:
前⾯讲过,通过类对象可以访问类变量,但⽆法修改类变量的值。这是因为,通过类对象修改类变量的值,不是在给“类变量赋值”,⽽是定义新的实例变量。例如,在 CLanguage 类体外,添加如下程序:
1. clang = CLanguage()
2. #clang访问类变量
6. clang.name = "Python教程"
7. clang.add = "c.biancheng/python"
8. #clang实例变量的值
9. print(clang.name)
10. print(clang.add)
11. #类变量的值
12. print(CLanguage.name)
13. print(CLanguage.add)
程序运⾏结果为:
显然,通过类对象是⽆法修改类变量的值的,本质其实是给 clang 对象新添加 name 和 add 这 2 个实例变量。
类中,实例变量和类变量可以同名,但这种情况下使⽤类对象将⽆法调⽤类变量,它会⾸选实例变量,这也是不推荐“类变量使⽤对象名调⽤”的原因。
另外,和类变量不同,通过某个对象修改实例变量的值,不会影响类的其它实例化对象,更不会影响同名的类变量。例如:
1. class CLanguage :
2. name = "xxx" #类变量
3. add = "" #类变量
4. def __init__(self):
5. self.name = "C语⾔中⽂⽹" #实例变量
6. self.add = "c.biancheng" #实例变量
7. # 下⾯定义了⼀个say实例⽅法
8. def say(self):
9. self.catalog = 13 #实例变量
10. clang = CLanguage()
11. #修改 clang 对象的实例变量
12. clang.name = "python教程"
13. clang.add = "c.biancheng/python"
14. print(clang.name)
15. print(clang.add)
16.
17. clang2 = CLanguage()
18. print(clang2.name)
19. print(clang2.add)
20. #输出类变量的值
21. print(CLanguage.name)
22. print(CLanguage.add)
程序运⾏结果为:
不仅如此,Python 只⽀持为特定的对象添加实例变量。例如,在之前代码的基础上,为 clang 对象添加 money 实例变量,实现代码为:
1. = 30
2. )
局部变量
除了实例变量,类⽅法中还可以定义局部变量。和前者不同,局部变量直接以“变量名=值”的⽅式进⾏定义,例如:
1. class CLanguage :
2. # 下⾯定义了⼀个say实例⽅法
3. def count(self,money):
4. sale = 0.8*money
5. print("优惠后的价格为:",sale)
6. clang = CLanguage()
7. unt(100)
通常情况下,定义局部变量是为了所在类⽅法功能的实现。需要注意的⼀点是,局部变量只能⽤于所在函数中,函数执⾏完成后,局部变量也会被销毁。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论