python类变量和实例变量在继承中如何取值

Python类与实例变量继承
本文探讨了Python中类变量和实例变量在不同继承场景下的取值规则,并通过实例演示了单继承、多继承和多级继承的具体行为。
部署运行你感兴趣的模型镜像

类变量:可在类的所有实例之间共享的变量
实例变量:同一个类对象可以创建多个实例类对象,类定义中有self标志的变量就是实例变量
类实例对象:类的实例是调用类对象来创建的。如:par = Parent(),par就是类Parent的一个类实例对象。

一、python类变量在继承中取值方式如下:

1,如果该变量在该类中有定义,则使用该值。
2,如果没有,将搜索父类,多继承时采用C3方法,一般不存在交叉的类都是从左到右顺序搜索。搜索过程中如果前面父类的值被重新赋值,则类变量值将改变成该值
关于C3方法详情请看http://www.nanerbang.com/article/40/
如果不想搞懂,直接调用 类名.mro() 打印出来看一下搜索顺序

二、python实例变量在继承中取值方式如下:

1,搜索方式和类变量一样,先找自己,再找父类,多继承也是使用C3,一般不存在交叉的类时按照从左到右顺序搜索
2,实例变量只会继承最开始的初始值,即使父类中的实例变量值被重新赋值,子类的值也不会跟着改变,仍会选择最开始的初始值。

三、举例证明

运行环境:python3.6
例一,继承关系Children1继承自Parent,Children2也继承自Parent。

class Parent(object):
    x = 1  # 类变量
    def __init__(self):
        self.y = 1  # 实例变量
class Children1(Parent):
    pass
class Children2(Parent):
    pass
par = Parent()  # 具体的类实例对象
child1 = Children1()  # 具体的类实例对象
child2 = Children2()  # 具体的类实例对象
print('-------------------------------------')
print('Parent.x=', Parent.x, ',Children1.x=', Children1.x, ',Children2.x=', Children2.x)
print('par.y=', par.y, ',child1.y=', child1.y, ',child2.y=', child2.y)

print('-------------------------------------')
Children1.x = 2
child1.y = 2
print('Parent.x=', Parent.x, ',Children1.x=', Children1.x, ',Children2.x=', Children2.x)
print('par.y=', par.y, ',child1.y=', child1.y, ',child2.y=', child2.y)

print('-------------------------------------')
Parent.x = 3
par.y = 3
print('Parent=', Parent.x, ',Children1=', Children1.x, ',Children2=', Children2.x)
print('par.y=', par.y, ',child1.y=', child1.y, ',child2.y=', child2.y)

print('-------------------------------------')
Children2.x = 4
child2.y = 4
print('Parent=', Parent.x, ',Children1=', Children1.x, ',Children2=', Children2.x)
print('par.y=', par.y, ',child1.y=', child1.y, ',child2.y=', child2.y)

输出结果:

-------------------------------------
Parent.x= 1 ,Children1.x= 1 ,Children2.x= 1
par.y= 1 ,child1.y= 1 ,child2.y= 1
-------------------------------------
Parent.x= 1 ,Children1.x= 2 ,Children2.x= 1
par.y= 1 ,child1.y= 2 ,child2.y= 1
-------------------------------------
Parent.x= 3 ,Children1.x= 2 ,Children2.x= 3
par.y= 3 ,child1.y= 2 ,child2.y= 1
-------------------------------------
Parent.x= 3 ,Children1.x= 2 ,Children2.x= 4
par.y= 3 ,child1.y= 2 ,child2.y= 4

总结:
1,对于类变量x,最开始Children1和Children2都没有赋值x,所以都等于1。当Children1赋值2之后值就变了,但Children2还是之前的1,当父类修改为3后,由于Children2一直没有赋值,所以等于修改后的父类的x值3,直到Children2自己赋值才是4。
2,对于实例变量y,最开始child1和child2都没有对y赋值,所以都等于1。当child1变成2之后就变成2,但child2还是之前的1,即使父类实例par改变y的值为3,child2还是为1。直到child2自己赋值为4才改变。

例二,GrandChildren继承自Children,Children继承自Parent

class Parent(object):
    x = 1
    def __init__(self):
        self.y = 1
class Children(Parent):
    pass
class GrandChildren(Children):
    pass
par = Parent()
child = Children()
grand = GrandChildren()
print('-------------------------------------')
print('Parent.x=', Parent.x, ',Children.x=', Children.x, ',GrandChildren.x=', GrandChildren.x)
print('par.y=', par.y, ',child.y=', child.y, ',grand.y=', grand.y)

print('-------------------------------------')
Children.x = 2
child.y = 2
print('Parent.x=', Parent.x, ',Children.x=', Children.x, ',GrandChildren.x=', GrandChildren.x)
print('par.y=', par.y, ',child.y=', child.y, ',grand.y=', grand.y)

print('-------------------------------------')
Parent.x = 3
par.y = 3
print('Parent.x=', Parent.x, ',Children.x=', Children.x, ',GrandChildren.x=', GrandChildren.x)
print('par.y=', par.y, ',child.y=', child.y, ',grand.y=', grand.y)

print('-------------------------------------')
GrandChildren.x = 4
grand.y = 4
print('Parent.x=', Parent.x, ',Children.x=', Children.x, ',GrandChildren.x=', GrandChildren.x)
print('par.y=', par.y, ',child.y=', child.y, ',grand.y=', grand.y)

输出结果:

-------------------------------------
Parent.x= 1 ,Children.x= 1 ,GrandChildren.x= 1
par.y= 1 ,child.y= 1 ,grand.y= 1
-------------------------------------
Parent.x= 1 ,Children.x= 2 ,GrandChildren.x= 2
par.y= 1 ,child.y= 2 ,grand.y= 1
-------------------------------------
Parent.x= 3 ,Children.x= 2 ,GrandChildren.x= 2
par.y= 3 ,child.y= 2 ,grand.y= 1
-------------------------------------
Parent.x= 3 ,Children.x= 2 ,GrandChildren.x= 4
par.y= 3 ,child.y= 2 ,grand.y= 4

总结:
1,对于类变量x,最开始Children和GrandChildren都没有赋值x,所以都等于1。当Children赋值2之后值就变了,GrandChildren也跟着变,当父类修改后,由于Children2在之前赋值为2,所以即使修改了父类的x,但也不会访问到他。GrandChildren自己赋值为3就会变成4,不影响Parent和GrandChildren。
2,对于实例变量y,最开始child和grand都没有对y赋值,所以都等于1。当child变成2之后就变成2,但grand还是最开始的初值1,即使父类实例par改变y的值为3,grand还是1。直到grand自己赋值为4才改变。

例三、GrandChildren继承自Children1和Children2,Children1继承自Parent,Children2继承自Parent

class Parent(object):
    x = 1  # 类变量
    def __init__(self):
        self.y = 1  # 实例变量
class Children1(Parent):
    pass
class Children2(Parent):
    def __init__(self):
        Parent.__init__(self)
        self.y = 90
class GrandChildren(Children1, Children2):
    pass
par = Parent()
child1 = Children1()
child2 = Children2()
grand = GrandChildren()
print('-------------------------------------')
print('Parent=', Parent.x, ',Children1.x=', Children1.x, ',Children2.x=', Children2.x, ',GrandChildren.x=',
      GrandChildren.x)
print('par.y=', par.y, ',child1.y=', child1.y, ',child2.y=', child2.y, ',grand.y=', grand.y)

print('-------------------------------------')
Children1.x = 2
child1.y = 2
print('Parent=', Parent.x, ',Children1.x=', Children1.x, ',Children2.x=', Children2.x, ',GrandChildren.x=',
      GrandChildren.x)
print('par.y=', par.y, ',child1.y=', child1.y, ',child2.y=', child2.y, ',grand.y=', grand.y)

print('-------------------------------------')
Children2.x = 3
child2.y = 3
print('Parent=', Parent.x, ',Children1.x=', Children1.x, ',Children2.x=', Children2.x, ',GrandChildren.x=',
      GrandChildren.x)
print('par.y=', par.y, ',child1.y=', child1.y, ',child2.y=', child2.y, ',grand.y=', grand.y)

print('-------------------------------------')
GrandChildren.x = 4
grand.y = 4
print('Parent=', Parent.x, ',Children1.x=', Children1.x, ',Children2.x=', Children2.x, ',GrandChildren.x=',
      GrandChildren.x)
print('par.y=', par.y, ',child1.y=', child1.y, ',child2.y=', child2.y, ',grand.y=', grand.y)

输出结果

-------------------------------------
Parent= 1 ,Children1.x= 1 ,Children2.x= 1 ,GrandChildren.x= 1
par.y= 1 ,child1.y= 1 ,child2.y= 90 ,grand.y= 90
-------------------------------------
Parent= 1 ,Children1.x= 2 ,Children2.x= 1 ,GrandChildren.x= 2
par.y= 1 ,child1.y= 2 ,child2.y= 90 ,grand.y= 90
-------------------------------------
Parent= 1 ,Children1.x= 2 ,Children2.x= 3 ,GrandChildren.x= 2
par.y= 1 ,child1.y= 2 ,child2.y= 3 ,grand.y= 90
-------------------------------------
Parent= 1 ,Children1.x= 2 ,Children2.x= 3 ,GrandChildren.x= 4
par.y= 1 ,child1.y= 2 ,child2.y= 3 ,grand.y= 4

总结:
1,对于类变量x,最开始Children1、Children2和GrandChildren都没有赋值x,所以都等于1。当Children1赋值2之后值就变了,但Children2还是之前的1,由于GrandChildren先继承Children1,所以等于修改后的Children1的x值2,即使Children2修改值为3,GrandChildren也是取值于Children1,直到GrandChildren自己赋值才是4。
2,对于实例变量y,最开始child1没有对y赋值所有搜索到父类值为1,但child2有初始值90,所以为90,grand没有初始化,先搜索child1,由于没有初始化,继续搜索child2,此时有初始化所以grand初始值为90。当child1赋值2之后就变成2,child2还是之前的90,grand也是90。即使child1和child2值都重新赋初值后,grand还是最开始的90。直到grand自己赋值为4才改变。

您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>好的,用户的问题是关于Python变量实例变量的区别及使用场景。首先,我需要回忆相关知识,确保准确无误。根据提供的三个引用,可以看出变量是在中所有实例之间共享的变量,而实例变量则是每个实例独有的。 首先,我需要明确两者的定义。变量定义在内部,但在方法之外,通常用于所有实例共有的属性,比如计数器或者默认值。实例变量则是在__init__方法中通过self定义的,每个实例拥有自己的副本,比如对象的特定属性。 接下来,区别方面,应该包括存储位置、修改影响、访问方式等。例如,变量被所有实例共享,修改变量会影响所有实例;而实例变量只属于特定实例,修改不会影响其他实例。同时,如果通过实例修改变量,实际上是创建了一个同名的实例变量,这可能引起混淆,需要特别注意。 使用场景方面,变量适合用于所有实例共有的数据,比如配置项或者统计实例数量。实例变量则适合每个对象独有的属性,比如人的姓名、年龄等。这部分需要结合实际例子说明,让用户更清楚何时使用哪种变量。 另外,需要注意常见的错误,比如在实例中错误地修改变量而导致意外行为,或者混淆两者的访问方式。可能需要举例说明正确错误的做法,帮助用户避免陷阱。 最后,生成相关问题时要围绕用户可能想深入了解的点,比如如何动态修改变量、如何正确继承时的变量处理、设计模式中的应用等。这些问题应能引导用户进一步学习,覆盖更广泛的应用场景。 总结下来,回答的结构应该是先定义,再区别,接着使用场景注意事项,最后提供示例代码常见问题解答。确保每个部分都引用正确的资料,并且在适当的位置添加引用标识。</think>### Python变量实例变量的区别及使用场景 #### 一、定义与核心区别 1. **变量** - 定义在内部,但在所有方法之外。 - 所有实例共享,修改会影响所有实例的访问结果。 - 示例:统计实例数量或定义默认配置。 ```python class Car: wheels = 4 # 变量(所有汽车默认有4个轮子) def __init__(self, brand): self.brand = brand # 实例变量 ``` 2. **实例变量** - 定义在`__init__`方法中,通过`self`绑定到实例。 - 每个实例独立拥有,修改仅影响当前实例。 - 示例:对象的个性化属性。 ```python car1 = Car("Toyota") car2 = Car("BMW") print(car1.brand) # 输出: Toyota print(car2.brand) # 输出: BMW ``` #### 二、关键区别对比 | 特性 | 变量 | 实例变量 | |---------------------|---------------------------|---------------------------| | **存储位置** | 命名空间 | 实例命名空间 | | **修改影响范围** | 所有实例自身 | 仅当前实例 | | **典型应用场景** | 共享配置、全局计数器 | 对象特有属性 | | **访问方式** | `名.变量` 或 `实例.变量` | 仅通过实例访问 | #### 三、使用场景分析 1. **变量的典型场景** - **全局配置管理**:例如数据库连接字符串。 ```python class Database: connection_str = "mysql://user:pass@localhost/db" ``` - **统计实例数量**:通过`__init__`中修改变量实现。 ```python class User: count = 0 def __init__(self): User.count += 1 ``` 2. **实例变量的典型场景** - **对象个性化属性**:例如用户的姓名、年龄。 ```python class Person: def __init__(self, name, age): self.name = name # 实例变量 self.age = age ``` #### 四、注意事项与常见问题 1. **修改变量时的陷阱** - 若通过实例修改变量,会**意外创建同名实例变量**,导致行为不一致: ```python class Test: shared = 10 t1 = Test() t1.shared = 20 # 创建了实例变量t1.shared,变量Test.shared仍为10 ``` 2. **继承中的优先级** - 子继承变量时,实例会优先访问自己的变量: ```python class Parent: value = 100 class Child(Parent): value = 200 print(Child().value) # 输出200 ``` #### 五、示例代码演示 ```python class Employee: raise_rate = 0.05 # 变量(加薪比例) def __init__(self, name, salary): self.name = name # 实例变量 self.salary = salary # 实例变量 def apply_raise(self): self.salary *= (1 + self.raise_rate) # 使用示例 emp1 = Employee("Alice", 50000) emp2 = Employee("Bob", 60000) # 修改变量会影响所有实例 Employee.raise_rate = 0.10 emp1.apply_raise() print(emp1.salary) # 输出55000 → 50000*(1+0.10) # 通过实例修改会创建实例变量 emp2.raise_rate = 0.15 emp2.apply_raise() print(emp2.salary) # 输出69000 → 60000*(1+0.15) ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值