python作为一门非常灵活、开放的语言,在学习成本、开发效率上又一定优势。但事物都是双面的,灵活以为这难以规范,一不注意细节可能就造成祸患。
以下代码展示了面向对象的一个坑:
class Sum:
num = 1
def __init__(self):
pass
@staticmethod
def add_num_static():
Sum.num += 1
@classmethod
def add_num_class(cls):
cls.num += 1
@classmethod
def getit_cls(cls):
print(cls.num)
def add_num_obj(self):
self.num += 1
def getit_self(self):
print(self.num)
obj_Sum = Sum()
print(getattr(obj_Sum, 'num') is Sum.num)
print(getattr(obj_Sum, 'num') is obj_Sum.num)
print("*" * 20 + "修改对象中的类属性" + "*" * 20)
obj_Sum.add_num_obj()
print(getattr(obj_Sum, 'num') is Sum.num)
print(getattr(obj_Sum, 'num') is obj_Sum.num)
以下是运行结果
不理解的朋友可以看下面:
obj_Sum = Sum()
print("*" * 20 + "修改对象中的类属性" + "*" * 20)
print(f'Sum类的类属性num的值是:{Sum.num}')
print(f'obj_Sum对象的属性num的值是:{obj_Sum.num}')
obj_Sum.getit_self()
print("*" * 20 + "使用静态方法修改类变量" + "*" * 20)
Sum.add_num_static()
print(f'Sum类的类属性num的值是:{Sum.num}')
print(f'obj_Sum对象的属性num的值是:{obj_Sum.num}')
print("*" * 20 + "使用类方法修改类变量" + "*" * 20)
Sum.add_num_class()
print(f'Sum类的类属性num的值是:{Sum.num}')
print(f'obj_Sum对象的属性num的值是:{obj_Sum.num}')
print("*" * 20 + "使用对象方法修改类变量" + "*" * 20)
obj_Sum.add_num_obj()
print(f'Sum类的类属性num的值是:{Sum.num}')
print(f'obj_Sum对象的属性num的值是:{obj_Sum.num}')
print("*" * 20 + "使用静态方法修改类变量" + "*" * 20)
Sum.add_num_static()
print(f'Sum类的类属性num的值是:{Sum.num}')
print(f'obj_Sum对象的属性num的值是:{obj_Sum.num}')
print("*" * 20 + "使用静态方法修改类变量" + "*" * 20)
Sum.add_num_static()
print(f'Sum类的类属性num的值是:{Sum.num}')
print(f'obj_Sum对象的属性num的值是:{obj_Sum.num}')
运行结果如下:
看到这大伙可能明白了,在对象中的类属性,在使用对象方法去修改后,会自动转换为对象属性。对象属性和类属性的在python中有不同的用处,部分玩惯java的朋友可能懒得写__init__,或者有的朋友不知道这个事情,就容易掉坑里。
补充:
1、getattr函数用于判断对象中是否存在属性和方法:
参数:
object。
name -- str类型,对象的属性或方法。
default -- 默认返回值,不设置默认值在没有对应属性时,则抛出异常。
2、is 用于判断标识符(变量名)的引用在内存中的位置是否相同,即是两个变量是否绝对相等。