DAY20 classmethod,staticmethod的详解
classmethod:类方法
@classmethod,将一个普通方法变成一个类方法,是一个装饰器。
在遇到不需要操作对象属性,而是操作类的静态属性的时候,就可以用到类方法。
谨记:类名和对象名都可以直接操作类方法,但是一般是用类名来操作。
###############################################################
例子1:延用前面的商品打折促销的例子,如果这时候,店庆结束了,折扣需要取消,那么要怎么处理?
#(1)延用先前的例子,店庆折扣为0.8折 class Goods: __discount = 0.8 def __init__(self,name,price): self.name = name self.__price = price @property def price(self): return self.__price * Goods.__discount shoes = Goods('nike鞋子',400) print(shoes.price) >>> 320.0 #(2) 这时候,店庆结束了,商品价格取消,当然也难不倒我们~ class Goods: __discount = 0.8 def __init__(self,name,price): self.name = name self.__price = price @property def price(self): return self.__price * Goods.__discount def change_discount(self,new_discount): Goods.__discount = new_discount shoes = Goods('nike鞋子',400) print(shoes.price) shoes.change_discount(1) print(shoes.price) >>> 320.0 400 #似乎没有什么大问题,折扣确实也改了,价格恢复了原价。但是细看还是可以发现端倪,为什么改变折扣的主体会是商品本身,
这是一件不合乎逻辑的事情;另外,在change_discount这个方法中,完全没有操作到对象的属性。所以这个时候,
classmethod就派上了用场。 #(3)classmethod类方法 class Goods: __discount = 0.8 def __init__(self,name,price): self.name = name self.__price = price @property def price(self): return self.__price * Goods.__discount @classmethod def change_discount(cls,new_discount): #类方法接受的第一个参数为cls,代表类本身 cls.__discount = new_discount shoes = Goods('nike鞋子',400) print(shoes.price) Goods.change_discount(1) #类方法通过类名来调用 print(shoes.price) >>> 400
问题来了,既然是类方法,那么对象能够调用吗?
shoes.change_discount(0.1) #对象名调用类方法
print(shoes.price)
>>>
40.0
#答案是可以的,但是不建议通过对象名来调用类方法。
###############################################################
例子2:如果我们想获取一个类中对象的个数?需要怎么做?
#(1)如果我们仅仅想和类中的属性交互而不是和实例交互?我们可以怎么办呢?我们可以在类的外部创建一个函数,
然后通过参数把这个函数与类关联起来,但是这种解决方法,不利于后期的代码维护。 def get_no_of_instance(cls): return cls.number_instance class Foo: number_instance = 0 def __init__(self): Foo.number_instance +=1 f1 = Foo() f2 = Foo() f3 = Foo() print(get_no_of_instance(Foo)) >>> 3 #(2)通过@classmethod类方法实现,通过类方法实现的好处就是:无论我们是通过类名还是对象名去调用,
它都会将类名作为第一个参数传入。 class Foo: number_instance = 0 def __init__(self): Foo.number_instance +=1 @classmethod def get_no_of_instance(cls): return cls.number_instance f1=Foo() f2=Foo() f3=Foo() print(Foo.get_no_of_instance()) >>> 3
staticmethod
往往有这种情况,如果在你定义的类中,有那么一些方法,他们不需要操作得到任何关于类中的属性和方法,也不需要用到对象的属性,仅仅是作为这个类的方法之一。这时候就可以用到staticmethod。
@staticmethod,也是一个装饰器,用来装饰一个不需要self参数,也不需要cls参数的方法。
例子1:
#(1)经常有一些跟类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法.
比如更改环境变量或者修改其他类的属性等能用到静态方法. 这种情况可以直接用函数解决,例子如下: IND = 'ON' def checkind(): return (IND == 'ON') class Kls(object): def __init__(self,data): self.data = data def do_reset(self): if checkind(): #通过调用函数,得到返回值 print('Reset done for:', self.data) def set_db(self): if checkind(): self.db = 'new db connection' print('DB connection made for:',self.data) ik1 = Kls(12) ik1.do_reset() ik1.set_db() #总结:这样用函数解决的方法固然可以,但是也会造成后期代码维护上的困扰,这个时候,就可以用到@staticmethod方法。 #(2) IND = 'ON' class Kls(object): def __init__(self, data): self.data = data @staticmethod def checkind(): return (IND == 'ON') def do_reset(self): if self.checkind(): print('Reset done for:', self.data) def set_db(self): if self.checkind(): self.db = 'New db connection' print('DB connection made for: ', self.data) ik1 = Kls(12) ik1.do_reset() ik1.set_db()