Python类变量赋值机制:实例赋值与类赋值的差异解析
本文深入解析Python中类变量的两种赋值方式及其对对象状态的影响。通过对比实例直接赋值与通过类名修改类变量,阐明Python属性查找机制(从实例__dict__到类__dict__)的工作原理。文章还补充了关于__dict__、__class__及__bases__的核心概念,以及类方法调用的底层逻辑,帮助开发者避免常见的变量作用域混淆问题。
类变量赋值的两种行为对比
为了直观展示差异,我们直接通过代码示例进行分析。
# -*- coding:utf-8 -*-
#面试题,写一个方法,将一行字符串中所有的单词数量统计出来
class Person(object):
TAG = "hello"
p1 = Person()
p2 = Person()
print p1.TAG #第一种赋值方式
print p2.TAG
print Person.TAG #第二种赋值方式
p1.TAG = "damn it"
print p1.TAG
print p2.TAG
print Person.TAG
运行上述代码后,输出结果显示:仅实例p1的TAG属性被修改为新的值"damn it",而p2和类本身的TAG仍保持原值。
hello
hello
hello
damn it
hello
hello
若希望所有通过该类创建的对象共享同一更新后的类变量值,应如何处理?
Person.TAG = "damn it"
再次运行程序,输出结果如预期所示:所有实例及类本身均读取到了最新的TAG值,问题得到解决。
hello
hello
hello
damn it
damn it
damn it
Python类、赋值与命名空间机制
补充知识:Python类、赋值操作与命名空间机制
在Python中,类本质上是一个命名空间。访问object.attr的过程,实际上是沿着属性查找链向上搜索的过程。
核心属性包括:__dict__、__class__和__bases__。
其中,__dict__存储实例、类或模块的属性字典;__class__指向实例所属的类对象;__bases__是一个元组,包含父类或超类列表。
属性与类的查找过程
属性查找(Attribute Lookup)过程如下:
def findAttr(obj , attr):
if attr in obj.__dict__:
return obj.__dict__[attr]
cls = obj.__class__
if attr in cls.__dict__:
return cls.__dict__[attr]
for super_cls in cls.__bases__:
if attr in super_cls.__dict__:
return super_cls.__dict__[attr]
return None
类继承树查找过程:
def classTree(cls,indent):
print('.'*indent + cls.__name__)
for super_cls in cls.__bases__:
classTree(super_cls,indent+4)
类方法调用的实现原理
赋值操作的两种主要方式:
class Test:
static_var = 1 #类属性相当与C++静态成员变量
def assign(self):
self.x = 1 #对象属性赋值
t = Test()
t.x = 2 #也可以这样 ,直接赋值
t.__dict__['x'] = 3 #也可以这样 , __dict__是对象空间词典,每个对象一份,类对象/模块也有
Test.add_static_var = 5 #也可以样新增一个类属性
类方法调用通常采用object.method()形式,在Python内部等价于扩展写法Class.method(object),两者效果一致。
Test.assign(t) print(t.x)
当使用object.method()时,object自动作为第一个参数传入method(self)中;而使用Class.method(object)时,则需要手动传入该对象。
命名空间与变量作用域详解
关于命名空间的具体行为:
x = 0
def print_global():
print(x) #打印全局
def print_local():
x = 1
print(x) #本地变量
class A:
x = 2 #类属性==C++静态成员变量 , print A.x
def m(self):
x = 3 #本地变量
self.x = 4 #对象属性
def change_global():
global x #修改全局变量,否则x = 100 ,是增加一个本地变量
x = 100
def print_enclosing():
x = 200
def nested():
print(x) #在闭包中引用本地变量
def change_in_enclosing():
x = 1
def nested():
nonlocal x
x = 2 #在闭包中改变本地变量, 如没有nonlocal x , 在又新增一个本地变量
以上即为Python中类变量两种赋值方式的区别详解,希望能为读者提供清晰的理解与参考,欢迎继续支持本站获取更多技术内容。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













