1、 属性
python中的属性跟其他语言有所区别,像在java中类的静态属性只能通过类来访问,实例对象无法去访问,反过来实例对象也无法调用类属性,但是python中有些不一样。首先网上大多数资料都没有把这个关系捋清楚,具体的我们往下进一步分析,先看他们的一个用法,直接上代码:
实例属性
实例属性通常在实例化时通过__init__方法初始化,或者在实例方法中动态添加。
class MyClass:
def __init__(self, value):
self.instance_attr = value # 实例属性
obj1 = MyClass(10)
obj2 = MyClass(20)
#实例属性的值对每个实例是独立的
print(obj1.instance_attr) # 输出: 10
print(obj2.instance_attr) # 输出: 20
类属性
class MyClass:
#申明类变量
shared_var = "I am shared among all instances"
#类的实例对象
obj1 = MyClass()
obj2 = MyClass()
#类的实例对象可以访问
print(obj1.shared_var) # 输出: I am shared among all instances
print(obj2.shared_var) # 输出: I am shared among all instances
#类也可以访问(类访问时改变了,)
MyClass.shared_var = "Now I am changed"
#实例对象访问的到的值也改变了
print(obj1.shared_var) # 输出: Now I am changed
print(obj2.shared_var) # 输出: Now I am changed
根据上述代码,似乎可以理解为这个类属性为所有实例对象共同拥有,也就是所有实例对象指向同一个属性,如果按照这个思路上面代码也能验证这点,当通过类调用类属性并改变其值之后再用对象实例去调用得到的值也跟着改变了。假如我们这个思路是正确的,那么反过来,当我们其中一个实例对象去调用这个值并改变它,那再通过类去调用得到的值也应该改变,事实真的是这样吗?废话不多说,直接上代码验证
class MyClass:
#申明类变量
shared_var = "I am shared among all instances"
#类的实例对象
obj1 = MyClass()
obj2 = MyClass()
#类的实例对象可以访问
print(obj1.shared_var) # 输出: I am shared among all instances
print(obj2.shared_var) # 输出: I am shared among all instances
#类也可以访问(类访问时改变了,)
MyClass.shared_var = "Now I am changed"
#实例对象访问的到的值也改变了
print(obj1.shared_var) # 输出: Now I am changed
print(obj2.shared_var) # 输出: Now I am changed
#上面代码中,类属性shared_var改变之后实例对象的属性shared_var也跟着改变
#接下来我给实例对象的属性重新赋值,但是类属性没有跟着变化
obj1.shared_var = "通过obj1更改shared_var"
obj2.shared_var = "通过obj2更改shared_var"
print(obj1.shared_var) # 通过obj1更改shared_var
print(obj2.shared_var) # 通过obj2更改shared_var
print(MyClass.shared_var ) # 输出 Now I am changed
通过上面代码发现,当设置实例对象属性shared_var之后
obj1.shared_var = "通过obj1更改shared_var",obj2.shared_var = "通过obj2更改shared_var"
类属性shared_var没有跟着变化
print(MyClass.shared_var ) # 输出 Now I am changed,
分析总结
当实例对象属性没有初始化值的时候指向类属性
- 实例对象没有初始化shared_var属性时就会指向类属性shared_var,这个时候类属性改变会影响实例对象的shared_var属性;
- 实例对象初始话过shared_var属性就不指向类属性shared_var,这个时候彼此改变不相互影响
2、方法
静态方法(staticmethod):通过装饰器@staticmethod装饰
class MyClass:
@staticmethod
def static_method():
print("This is a static method.")
MyClass.static_method() # 调用静态方法,不传递参数
特点
- 不需要将类本身作为第一个参数(如 self 或 cls)
- 不需要访问类的任何状态属性
类方法(classmethod):通过装饰器@classmethod装饰
class MyClass:
class_var = "I am a class variable."
@classmethod
def class_method(cls):
print(cls.class_var)
MyClass.class_method() # 调用类方法
特点
- 调用的时候传递了参数类的上下文cls
- 需要访问类的任何状态属性
两者的根本区别
- @staticmethod装饰的函数不访问类的任何状态,不传递上下文参数cls;
- @classmethod装饰的函数需要访问类的状态,传递上下文参数cls;