@classmethod的定义

@classmethod是装饰器,用来指定类中的某个方法是类的绑定方法。

@classmethod装饰与否的区别

  • 实例的绑定方法

在类中定义的方法默认是实例的绑定方法,实例的绑定方法第一参数是self,self指代实例的命名空间内存地址。必须有实例才能调用。

调用方式有2种:一是“实例.方法名()”,二是“类名.方法名(实例名)”,调用的前提是已创建了实例,没有实例调用会报错!

  • 类的绑定方法

在类中定义的方法前加上@classmethod装饰表示它是类的绑定方法,类中的绑定方法第一参数是cls,cls指代类的命名空间内存地址。有没有实例都可以调用。

调用方式有2种:一种是“类名.方法名()”,二是“实例.方法名()”,调用前不需要创建实例,没有实例也可以调用。

@classmethod运用场景

常见的运用场景有2种,一是调用类的绑定方法创建实例;二是修改类的私有属性。

案例一,调用类的绑定方法创建实例:

import time


class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    @classmethod
    def today(cls):
        now = time.localtime()
        return Date(now.tm_year, now.tm_mon, now.tm_mday)


today = Date.today()
print(f'今天是“{today.year}年{today.month}月{today.day}日”')

out:
今天是“2020年11月9日”

讲解

上述Date类中有2个方法,一个是__init__即实例的初始化方法,另一个是today即类的绑定方法,通过调用Date.today()可以无参数自主创建实例。这个在实际生产中经常会用到。请用心体类的绑定方法创建实例的方式。

案例二,调用类的绑定方法修改类的私有属性:

class Goods:
    __discount = 1  # 折扣比例

    def __init__(self, name, price):
        self.name = name  # 商品名称
        self.price = price  # 商品价格

    @property
    def total(self):  # 商品总价
        return self.price*self.__discount

    @classmethod
    def change_discount(cls, n):
        Goods.__discount = n


apple = Goods('苹果', 5)
print(apple.total)
Goods.change_discount(0.8)
print(apple.total)
pear = Goods('梨', 4)
print(pear.total)

out:
5
4.0
3.2

上述代码中类的私有属性discount是控制全场商品折扣比例,在类的外部无法修改私有属性。只能在类的内部定义类的绑定方法来修改类的私有属性。

请注意实例的属性和类的属性区别:

实例的属性是存储在实例各自的命名空间中,所以有多少个实例就会有多少份相应的实例属性。

类的属性是存储在类的命名空间中,所以类的属性只有一份(无论有多少个实例)。