python中类变量是属于类的,不属于具体的对象,所有对象共享一个类变量。类变量可以通过类名.变量名
访问,也可以通过实例化后的对象.变量名
访问。那么,如果我给对象的变量起的名字和类变量同名会如何?我们写代码测试一下:
class Foo:
name = "hello"
def set_instance_name(self, name):
self.name = name
def get_instance_name(self):
return self.name
def get_class_name(self):
return Foo.name
foo = Foo()
print(f"{Foo.name=}")
print(f"{foo.get_instance_name()=}")
print(f"{foo.get_class_name()=}")
foo.set_instance_name("world")
print(f"{Foo.name=}")
print(f"{foo.get_instance_name()=}")
print(f"{foo.get_class_name()=}")
输出:
Foo.name='hello'
foo.get_instance_name()='hello'
foo.get_class_name()='hello'
Foo.name='hello'
foo.get_instance_name()='world'
foo.get_class_name()='hello'
可以看到,当读取self.name
时,如果已经有实例变量则访问实例变量,否则访问类变量。当写入self.name时,会创建新的实例变量,不会改变类变量。
因此,类变量可以作为“实例化”对象的默认值使用。比如这段神奇的代码:
class Foo:
name = "hello"
def __init__(self) -> None:
self.name = self.name
foo = Foo()
print(f"{foo.name=}")
foo.name = "world"
print(f"{foo.name=}")
print(f"{Foo.name=}")
__init__
函数中出现了self.name=self.name
,是不是很神奇?这里等于号右边因为还没有名字叫name
的实例变量,因此访问到了类变量,等于号左边是实例变量。在创建后,因为实例变量有了name
,之后再访问self.name
就访问到了实例变量。