实例变量与类变量不得不说的二三事

实例变量与类变量不得不说的二三事

1. 类变量作用及解析

类变量:实例共用的属性。 比方说country 这个属性如果设置为实例属性,创建5个对象的时候,country 就需要初始化5次,但这个属性对于各个实例是相同的,每次都需要创建会造成资源浪费。类变量只会在创建类的时候生成一次,对于不同对象来说无区别的对象我们可以设置为类变量。
class Chinese:
    country = 'China'
    def __init__(self, name, age,country):
        self.name = name
        self.age = age
        self.country = country  

2. 类变量、实例变量查找优先级

优先查找实例变量,找不到再去查找类变量。就是说类变量和实例变量名相同的情况下,返回的是实例变量的值,代码如下:
class Chinese:
    country = 'China'
    age = 72
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        print(self, 'is talking Chinese')
if __name__ == '__main__':
    DY = Chinese("DY", "18")
    print(DY.age)
    
执行结果:
18  # 18为实例DY的属性值

3. 实例增删改查类的变量、方法

实例是可以直接操作类的变量或方法的,可进行查询、更改、新增、删除的,如果是使用这些方法时,仅推荐操作实例属性,其他属性因为存储在类的命名空间内,操作的话会影响其他实例,Python真的是很不严谨;但其实实例的属性、方法也是不推荐操作如更改、删除的,这就引入了私有变量或方法。

class Chinese:
    country = 'China'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        print(self, 'is talking Chinese')

    @staticmethod
    def nationality():
        print("国籍归属于{}".format(Chinese.country))


if __name__ == '__main__':
    DY = Chinese("DY", 18)
    print(DY.age)  # 查询实例变量值
    DY.age = 19   # 更改实例变量的值,思考更改类变量的值?
    print(DY.age)
    DY.sex = "女"  # 对象新增实例变量
    print(DY.sex)
    del DY.talk  # 删除实例属性,慎用删除
    print(DY.talk)

4. 实例可以更改类变量值吗?

实例对类变量赋值(更改类变量)为什么未改变类变量值?对象给类变量赋值实际是给实例增加一种新的属性,是在对象内存空间中新增了一个变量,而使用变量的时候又是优先查找实例变量,所以打印对象的类变量时,实际是查的对象的实例属性,从根本上并未影响到类变量,也就不会影响到其他对象的类变量值。 简而言之,你觉得是在更改类变量的值,实际是给实例新增了一个实例属性。
class Chinese:

    country = 'China'
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        print(self, 'is talking Chinese')

if __name__ == '__main__':
    DY1 = Chinese("DY", "18")
    DY2 = Chinese("DY", "19")
    DY1.country = "zhongguo"
    print(DY1.country)
    print(DY2.country)

执行结果:
zhongguo  # 实际相当于给实例DY1新增了个实例属性
China     # 实例DY2并不受影响

5. 慎用del 删除类变量、类方法、实例方法

在Python中,类变量、类方法、实例方法存储在类的内存空间中,对象删除这些属性、方法是从类内存空间中真正删除,至于为什么可以这么做,这也是Python不严谨的地方,建议大家最好不要这么做。
class Chinese:

    country = 'China'
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        print(self, 'is talking Chinese')

if __name__ == '__main__':
    DY1 = Chinese("DY", "18")
    del DY1.country
    print(Chinese.country)
    
执行结果:
Traceback (most recent call last): 
  File "question.py", line 665, in <module> 
    del DY1.country 
AttributeError: country

6. 类属性慎用可变数据结构

class Chinese:
    country = 'China'
    populations = []

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def talk(self):
        print(self, 'is talking Chinese')

    @staticmethod
    def nationality():
        print("国籍归属于{}".format(Chinese.country))

    def add_people(self):
        Chinese.populations.append(self.name)


if __name__ == '__main__':
    DY1 = Chinese("DY", 18)
    DY2 = Chinese("DY1", 18)
    DY1.add_people()
    print(DY1.populations)
    DY2.add_people()
    print(DY2.populations)
   
执行结果:
['DY'] 
['DY', 'DY1']
由执行结果可以看出,两个实例同时操作类变量时是会相互影响的, 对象DY1操作populations属性也会影响到DY2的populations ,如果是在程序中是会出bug的,而且问题不好查找,就好比说对象A与对象B同时在做任务,并且共享任务列表,对象A完成后发通知说任务已完成,导致对象B实际未做完也发通知报告已完成。 划重点:可变数据结果一般不能用作类变量的值。如果变量的值为可变数据,需要写在__init__里面,写成self. populations = [],这样在初始化对象的时候,每个对象的populations的值都会初始化为一个空列表,对象间属性独立。  
上一篇:nltk.download()下载不了怎么办​??​


下一篇:2021-05-12