python类变量和实例变量

python类变量和实例变量

在类体中,根据变量定义的位置不同,以及定义的方式不同,类属性可细分为以下 3 种类型:

  1. 类体中,所有函数之外:此范围定义的变量,称为类属性类变量
  2. 类体中,所有函数内部:以“self.变量名”的方式定义的变量,称为实例属性实例变量
  3. 类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量

类变量(类属性)

定义

类变量指的是在类中,但在各个类方法外定义的变量。举个例子:

class People:
    # 定义两个类变量
    name = "lilei"
    age = 15

    def __init__(self):
        pass

上面的程序中,nameage就是类变量

调用

类变量的调用方式有 2 种:

  • 使用类名直接调用
  • 使用类的实例化对象调用(不推荐)

类名直接调用

# 使用类名直接调用
print(People.name)
print(People.age)
print("="*5, "修改类变量的值", "="*5)
# 修改类变量的值
People.name = "hanmeimei"
People.age = 18
print(People.name)
print(People.age)
lilei
15
===== 修改类变量的值 =====
hanmeimei
18

可以看到,通过类名不仅可以调用类变量,也可以修改它的值。

类的实例化对象调用(不推荐)

【注】此方式不推荐使用,原因后面解释

class People:
    # 定义两个类变量
    name = "lilei"
    age = 15


a_man = People()
print(a_man.name)
print(a_man.age)
lilei
15

特性

  • 所有类的实例化对象都同时共享类变量
    • 类变量在所有实例化对象中是作为公用资源存在的。
    • 类变量为所有实例化对象共有,通过类名修改类变量的值,会影响所有的实例化对象
class People:
    # 定义两个类变量
    name = "lilei"
    age = 15


print("修改前,实例1中类变量的值:")
man_a = People()
print(man_a.name)
print(man_a.age)
print("修改前,实例2中类变量的值:")
man_b = People()
print(man_b.name)
print(man_b.age)


People.name = "hanmeimei"
People.age = 233
print("修改类变量后,实例1中类变量的值:")
print(man_a.name)
print(man_a.age)
print("修改类变量后,实例2中类变量的值:")
print(man_b.name)
print(man_b.age)
修改前,实例1中类变量的值:
lilei
15
修改前,实例2中类变量的值:
lilei
15
修改类变量后,实例1中类变量的值:
hanmeimei
233
修改类变量后,实例2中类变量的值:
hanmeimei
233

由结果可以看出,通过类名修改类变量,会作用到所有的实例化对象(例如这里的 man_a 和 man_b)

通过类对象是无法修改类变量的。通过类对象对类变量赋值,其本质将不再是修改类变量的值,而是在给该对象定义新的实例变量

实例变量(实例属性)

定义

实例变量指的是在任意类方法内部,以“self.变量名”的方式定义的变量,其特点是只作用于调用方法的对象

class Person:
    def __init__(self):
        self.name = "zhangsan"
        self.age = 18

    def add_instance_val(self):
        self.single = True

Person类中,name,age,single都是实例变量,其中,

  • __init__函数在创建类对象的时候会自动调用,从而将会自动定义name,age这两个实例变量
  • single这个实例变量只有在add_instance_val这个函数执行的时候才会被定义

例1

class Person:
    def __init__(self):
        self.name = "zhangsan"
        self.age = 18

    def add_instance_val(self):
        self.single = True


a_man = Person()
print(a_man.name)
print(a_man.age)
print(a_man.single)
zhangsan
18



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

C:\Users\name\AppData\Local\Temp/ipykernel_10428/3992591591.py in <module>
     11 print(a_man.name)
     12 print(a_man.age)
---> 13 print(a_man.single)


AttributeError: 'Person' object has no attribute 'single'

我们可以看到由于没有调用add_instance_val这个方法,因此single这个值没有被定义

a_man.add_instance_val()
print(a_man.single)
True

调用完add_instance_val方法之后,就可以取到single这个值了

例2

# 实例化对象
a = Person()
dir(a)
['__class__',
 '__delattr__',
......
 '__weakref__',
 'add_instance_val',
 'age',
 'name']

我们可以看到实例化对象后,这个对象就有了name,age属性和add_instance_val这个方法

a.add_instance_val()
dir(a)
['__class__',
 '__delattr__',
......
 '__weakref__',
 'add_instance_val',
 'age',
 'name',
 'single']

只有我们运行add_instance_val实例方法之后,这个对象才有了single属性

赋值

定义完实例之后,可以直接以instance.attribute = val的格式进行赋值
注:通过类对象可以访问类变量,但无法修改类变量的值

class Person:
    salary = "100m"

    def __init__(self):
        self.name = "张三"
        self.age = 18

    def add_instance_val(self):
        self.single = True
bb = Person()
print(bb.name)
print(bb.age)

# 修改属性
bb.name = "法外狂徒"
bb.age = 20
print("==========修改属性之后==========")
print(bb.name)
print(bb.age)


print("==========初始的类变量==========")
print(Person.salary)

print("==========尝试通过对象,修改类变量==========")
# 尝试修改
bb.salary = "1000m"

print("==========修改后的类变量==========")
print(Person.salary)
print("==========修改后的实例变量==========")
print(bb.salary)
张三
18
==========修改属性之后==========
法外狂徒
20
==========初始的类变量==========
100m
==========尝试通过对象,修改类变量==========
==========修改后的类变量==========
100m
==========修改后的实例变量==========
1000m

可以看到类变量并没有被修改

这是因为,通过类对象修改类变量的值,不是在给“类变量赋值”,而是定义新的实例变量

显然,通过类对象是无法修改类变量的值的,本质其实是给bb对象新添加了salary这个实例变量

类中,实例变量和类变量可以同名,但这种情况下使用类对象将无法调用类变量,它会首选实例变量,这也是不推荐“类变量使用对象名调用”的原因。

特性

  • 和类变量不同,通过某个对象修改实例变量的值,不会影响类的其它实例化对象,更不会影响同名的类变量。例如:
class Person:
    name = "类变量名字"  # 类变量

    def __init__(self):
        self.name = "实例变量名字"   # 实例变量

    # 通过实例方法定义实例变量
    def add_val(self):
        self.catalog = 13  # 实例变量


# 定义两个实例
instance_a = Person()
instance_b = Person()
print("***修改类变量前***\n")
print(f"类变量Person.name为: {Person.name}")
print(f"instance_a实例变量instance_a.name为: {instance_a.name}")
print(f"instance_b实例变量instance_b.name为: {instance_b.name}")

print("\n***修改 instance_a 对象的实例变量***\n")
# 修改 instance_a 对象的实例变量
instance_a.name = "instance_a更换后的名字"

print(f"类变量Person.name为: {Person.name}")
print(f"instance_a实例变量instance_a.name为: {instance_a.name}")
print(f"instance_b实例变量instance_b.name为: {instance_b.name}")
***修改类变量前***

类变量Person.name为: 类变量名字
instance_a实例变量instance_a.name为: 实例变量名字
instance_b实例变量instance_b.name为: 实例变量名字

***修改 instance_a 对象的实例变量***

类变量Person.name为: 类变量名字
instance_a实例变量instance_a.name为: instance_a更换后的名字
instance_b实例变量instance_b.name为: 实例变量名字

局部变量

除了实例变量,类方法中还可以定义局部变量。和前者不同,局部变量直接以“变量名=值”的方式进行定义,例如:

class Employee:
    # 定义increase_salary实例方法
    def increase_salary(self, now_salary):
        rate = 200
        new_salary = rate * now_salary
        print("加薪后的工资为:", new_salary)


zz = Employee()
zz.increase_salary(50000)
加薪后的工资为: 10000000

常情况下,定义局部变量是为了所在类方法功能的实现。需要注意的一点是,局部变量(上例中的ratenew_salary)只能用于所在函数中,函数执行完成后,局部变量也会被销毁

参考文章

posted @   zlbingo  阅读(123)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示