python中的@classmethod的作用

一、简介

1.1 描述

classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等。

1.2 语法

@classmethod

1.3 返回值

返回函数的类方法。

1.4 实例

以下实例展示了@classmethod 的使用方法:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
class A(object):
    bar = 1
    def func1(self):  
        print ('foo') 
    @classmethod
    def func2(cls):
        print ('func2')
        print (cls.bar)
        cls().func1()   # 调用 foo 方法
 
A.func2()               # 不需要实例化

二、作用
很多博客只是说@calssmethod的作用就是“可以不需要实例化,直接类名.方法名()来调用。这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁”。很抽象,其实具体作用如下:

@classmethod的作用实际是可以在class内实例化class,一般使用在有工厂模式要求时。作用就是比如输入的数据需要清洗一遍再实例化,可以把清洗函数定义在class内部并加上@classmethod装饰器已达到减少代码的目的。总结起来就是:@class method可以用来为一个类创建一些预处理的实例。

1.1 简单实例
例如:看下面的定义的一个时间类:
 

class Data_test(object):
    day=0
    month=0
    year=0
    def __init__(self,year=0,month=0,day=0):
        self.day=day
        self.month=month
        self.year=year
    def out_date(self):
        print("year :",self.year)
        print("month :",self.month)
        print("day :",self.day)
t=Data_test(2020,1,1)
t.out_date()
 

输出:

year :2020
 
month :1
 
day :1

符合期望。

继续,如果用户输入的是 "2016-8-1" 这样的字符格式,那么就需要调用Date_test 类前做一下处理:

string_date='2020-1-1'
 
year,month,day=map(int,string_date.split('-'))
 
s=Data_test(year,month,day)

先把‘2020-1-1’ 分解成 year,month,day 三个变量,然后转成int,再调用Date_test(year,month,day)函数。 也很符合期望。

那我可不可以把这个字符串处理的函数放到 Date_test 类当中呢?那么@classmethod 就开始出场了:
 

class Data_test2(object):
    day=0
    month=0
    year=0
    def __init__(self,year=0,month=0,day=0):
        self.day=day
        self.month=month
        self.year=year
    @classmethod
    def get_date(cls,data_as_string):
 
        #这里第一个参数是cls, 表示调用当前的类名
 
        year,month,day=map(int,data_as_string.split('-'))
        date1=cls(year,month,day)     #返回的是一个初始化后的类
        return date1
 
    def out_date(self):
        print("year :",self.year)
        print("month :",self.month)
        print("day :",self.day)

在Date_test类里面创建一个成员函数, 前面用了@classmethod装饰。 它的作用就是有点像静态类,比静态类不一样的就是它可以传进来一个当前类作为第一个参数。那么如何调用呢?

r=Data_test2.get_date("2020-1-1")
 
r.out_date()

输出: 

year :2020
 
month :1
 
day :1

这样子等于先调用get_date()对字符串进行出来,然后才使用Data_test的构造函数初始化。

 这样的好处就是你以后重构类的时候不必要修改构造函数,只需要额外添加你要处理的函数,然后使用装饰符 @classmethod 就可以了。

1.2 深入理解实例

(1)Factory methods(工厂方法模式)

工厂方法模式即用户只需通过固定的接口获得一个对象的实例,降低了维护的复杂性。

看一个例子:

class Pizza(object):
    def __init__(self, ingredients):   #ingredient:原料种类
        self.ingredients = ingredients
 
    @classmethod
    def from_fridge(cls, fridge):
        return cls(fridge.get_cheese() + fridge.get_vegetables())

这里的class method, from_fridge( cls, fridge)  返回Pizza对象,这个Pizza是冰箱里的Pizza。假如我们用静态方法来写的话,还需要在函数中hardcode the Pizza class name,继承Pizza。 在Python官方doc中也有提到:
 

Also see classmethod() for a variant that is useful for creating alternate class constructors.

总结起来就是,class method可以用来为一个类创建一些预处理的实例。

(2)调用static method

看这个例子:

class Pizza(object):
    def __init__(self, radius, height):
        self.radius = radius
        self.height = height
 
    @staticmethod
    def compute_area(radius):
        return math.pi * (radius ** 2)
 
    @classmethod
    def compute_volume(cls, height, radius):
        return height * cls.compute_area(radius)    #调用@staticmethod方法
 
    def get_volume(self):
        return self.compute_volume(self.height, self.radius)   

 

  • 56
    点赞
  • 156
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值