类方法:必须通过类的调用,而且此方法的意义:就是对类里面的变量或者方法进行修改添加。
例一个商店,店庆全场八折,代码怎么写呢?
class Goods: __discount = 0.8 # 折扣 def __init__(self,name,origin_price): self.name = name self.__price = origin_price @property def price(self): return self.__price * Goods.__discount apple = Goods('apple',5) banana = Goods('banana',8) print(apple.price) print(banana.price) ''' 执行输出: 4.0 6.4 '''
现在折扣变了,店庆结束,恢复原价。如何修改__discount变量呢?不能这么写。
Goods._Goods__discount = 1
怎么办呢?定义一个方法,修改属性
class Goods: __discount = 0.8 def __init__(self,name,origin_price): self.name = name self.__price = origin_price @property def price(self): return self.__price * Goods.__discount def change_discount(self,new_discount): # 修改折扣 Goods.__discount = new_discount #修改了全局的 apple = Goods('apple',5) banana = Goods('banana',8) apple.change_discount(1) #修改折扣为1 print(apple.price) print(banana.price) ''' 执行输出: 5 8 '''
但是修改类静态变量,不需要实例化才对啊。如果要改变折扣是全场的事情不牵扯到一个具体的物品 所以不应该使用对象来调用这个方法。
类函数(@classmethod):即类方法, 更关注从类中调用方法, 而不是在实例中调用方法
不依赖对象的方法 就应该定义成类方法,类方法可以任意操作类中的静态变量
class Goods: __discount = 0.8 # 折扣 def __init__(self,name,origin_price): self.name = name self.__price = origin_price # 原价 @property def price(self): # 价格 return self.__price * Goods.__discount @classmethod def change_discount(self,new_discount): Goods.__discount = new_discount Goods.change_discount(1) # 类方法 可以直接被类调用 不需要默认传对象参数 只需要传一个类参数就可以了 apple = Goods('apple',5) banana = Goods('banana',8) print(apple.price) print(banana.price) ''' 执行输出: 5 8 '''
练习题
假设我有一个学生类和一个班级类,想要实现的功能为:
- 执行班级人数增加的操作、获得班级的总人数;
- 学生类继承自班级类,每实例化一个学生,班级人数都能增加;
- 最后,我想定义一些学生,获得班级中的总人数。
class C: count = 0 def __init__(self): C.cou() @classmethod def cou(cls): cls.count += 1 obj = C() obj = C() obj = C() obj = C() obj = C() obj = C() obj = C() obj = C() obj = C() obj = C() obj = C() print(C.count) # 11
思考:这个问题用类方法做比较合适,为什么?因为我实例化的是学生,但是如果我从学生这一个实例中获得班级总人数,在逻辑上显然是不合理的。同时,如果想要获得班级总人数,如果生成一个班级的实例也是没有必要的。
class Student: __num = 0 def __init__(self, name, age): self.name = name self.age = age Student.addNum() # 写在__new__方法中比较合适,但是现在还没有学,暂且放到这里 @classmethod def addNum(cls): cls.__num += 1 @classmethod def getNum(cls): return cls.__num a = Student('Tony', 18) b = Student('John', 19) c = Student('Linda', 20) print(Student.getNum()) # 3