python @classmethod
写在前面
写博客的时候,我发现拖延症很严重,本来昨天要开始写的,结果东看看,西翻翻,啥也没落实下来。时间过去了,口袋里的收获却寥寥无几。讨厌这样的自己。我要戒掉这个不好的毛病。
拖延症的底层原因之一是:不知如何下手
拖延症的底层原因之二是:每天都重复,疲了,累了
这里仅代表我自己
1..什么是classmethod
classmethod是用来指定一个类的方法为类方法
长的像下面这个样子
class cc:
@classmethod
def f(cls, arg1, arg2, ...): ...
cls通常用作类方法的第一参数 跟self有点类似( __init__里面的slef通常用作实例方法的第一参数)。即通常用self来传递当前类对象的实例,cls传递当前类对象。
self 和cls 没有特别的含义,作用只是把参数绑定到普通的函数上, 不一定非得是slef 或cls , 可以换成别的xxx
2..为什么会出现classmethod
(下面的比较琐碎,也不讲章法,但是这些点点滴滴我想记录下来,因为他们帮助我拼凑了这类知识的框架体系。我很喜欢用拼凑这个词,每次碰到一个完全陌生的鬼,总是这儿点点,那儿翻翻,每个足迹都会留下一点点碎片,慢慢的,逛的久了,再动手写写,基本上这一类内容在我脑子里渐渐形成个轮廓了,这个轮廓就是这些碎片拼凑出来的)
1--classmethod设计的目的是什么呢?事实上与Python面向对象编程有关的,由于Python不支持多个的參数重载构造函数,比方在C++里,构造函数能够依据參数个数不一样。能够写多个构造函数。Python为了解决问题,採用classmethod修饰符的方式,这样定义出来的函数就能够在类对象实例化之前调用这些函数,就相当于多个构造函数,解决多个构造函数的代码写在类外面的问题。
2---类最基本的作用是实例化出一个对象,但是有的时候再实例化之前,就需要先和类做一定的交互,这种交互可能会影响实际实例化的过程,所以必须放在调用构造函数之前。大概也可能是因为这个原因出现了classmethod
3---直接一点来说,我们知道对于一个普通的类,我们要使用其中的函数的话,需要对类进行实例化,而一个类中,某个函数前面加上了staticmethod或者classmethod的话,那么这个函数就可以不通过实例化直接调用,
可以通过类名进行调用的
4---@classmethod 定义的类方法是可选构造函数中,我们定义了一个类方法,类方法的第一个参数(cls)指代的就是类本身。类方法会用这个类来创建并返回最终的实例。使用类方法的另一个好处就是在继承的时候,保证了子类使用可选构造函数构造出来的类是子类的实例而不是父类的实例。
3..classmethod有什么用
在Java等语言中,这类功能通常通过工厂类(Factory)实现,先初始化一个工厂类的实例,然后由这个工厂类的实例构造实际需要的实例。在Python中,普通类完全可以替代Factory,而对于支持配置的Factory,就对应到相应的classmethod。
4..举第一个例子来理解classmethod
(因为我功力太浅,我真的没能理解@classmethod所起到的作用,但是知乎灵剑的这篇博客不明觉历,我还是先把这个例子这,说不定哪一天就想通了)
1)有一个插件系统,可以自动从插件目录中加载外部插件

2)Plugin是用户自定义插件的基类,它的构造函数接受一个api_interface的参数,把它保存到实例中。当想用这个接口的时候,调callback就好了,达到扩展功能的目的
3)事情不可能一成不变,要升级了,需要重新设计插件系统
4)插件数量变更多了,每个插件只干自己的事(比如,比如缝纫机插件只管缝衣服的事情,盖房子插件只管盖房子的事,警察插件只管抓坏人的事),那希望安装注册插件的时候希望插件声明好自己只干哪几样活(比如挖土插件要说好 :我只负责挖土,不负责缝衣服和盖房子)。
5)api_interface也变了,但是希望旧接口不做任何改变就能直接用
6)旧插件也不做任何改动就可以继续使用。
7)基于这样的需求,我们需要在构造plugin对象之前,就先从类中获取一定的信息。

5..再举个例子来理解classmethod的使用方法
这个是CSDN的dyh4201,链接都放下面了,这个通俗易懂,总感觉@classmethod还能发挥更大的用途,只是我还没完全参透,举不出例子来
看下面的定义的一个时间类: 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 :"
print self.year
print "month :"
print self.month
print "day :"
print self.day t=Data_test(2016,8,1)
t.out_date() 输出:
year :
2016
month :
8
day :
1 符合期望。 如果用户输入的是 "2016-8-1" 这样的字符格式,那么就需要调用Date_test 类前做一下处理: string_date='2016-8-1'
year,month,day=map(int,string_date.split('-'))
s=Data_test(year,month,day) 先把‘2016-8-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,string_date.split('-'))
date1=cls(year,month,day)
#返回的是一个初始化后的类
return date1 def out_date(self):
print "year :"
print self.year
print "month :"
print self.month
print "day :"
print self.day 在Date_test类里面创建一个成员函数, 前面用了@classmethod装饰。 它的作用就是有点像静态类,比静态类不一样的就是它可以传进来一个当前类作为第一个参数。 那么如何调用呢? r=Data_test2.get_date("2016-8-6")
r.out_date()
输出:
year :
2016
month :
8
day :
1 这样子等于先调用get_date()对字符串进行出来,然后才使用Data_test的构造函数初始化。 这样的好处就是你以后重构类的时候不必要修改构造函数,只需要额外添加你要处理的函数,然后使用装饰符 @classmethod 就可以了。
6.在继承时也能工作的很好:
类方法的一个主要用途就是定义多个构造器。它接受一个class 作为第一个参数(cls)。在继承时也能工作的很好:

7..还有其他待挖掘
关于@classmethod,以后要是发现新的用途或者有更深的理解了,我再继续加到下面
参考
https://www.cnblogs.com/zfyouxi/p/5222811.html
http://30daydo.com/article/89
https://www.zhihu.com/question/20021164
https://blog.csdn.net/mr_hui_/article/details/82939979
https://www.cnblogs.com/agnewee/p/5653936.html
python @classmethod的更多相关文章
- python @classmethod 的使用场合
python @classmethod 的使用场合 官方的说法: classmethod(function)中文说明:classmethod是用来指定一个类的方法为类方法,没有此参数指定的类的方法为实 ...
- python @classmethod和@staticmethod区别
python 类方法和静态方法区别 python @classmethod和@staticmethod区别 Python中至少有三种比较常见的方法类型,即实例方法,类方法.静态方法.它们是如何定义的呢 ...
- Python classmethod 修饰符
描述 classmethod修饰符对应的函数不需要实例化,不需要self参数,但第一个参数需要是表示自身类的cls参数,可以调用类的属性,类的方法,实例化对象等. 语法 classmethod语法: ...
- python classmethod 和 staticmethod的区别
https://stackoverflow.com/questions/12179271/meaning-of-classmethod-and-staticmethod-for-beginner 1. ...
- python -- @classmethod @staticmethod区别和使用
python中的定义: class MyClass: ... @classmethod # classmethod的修饰符 def class_method(cls, arg1, arg2, ... ...
- Fluent Python: Classmethod vs Staticmethod
Fluent Python一书9.4节比较了 Classmethod 和 Staticmethod 两个装饰器的区别: 给出的结论是一个非常有用(Classmethod), 一个不太有用(Static ...
- python classmethod方法 和 staticmethod
classmethod() 是一个类方法,用来装饰对应的函数.被classmethod 装饰之后就无需实例化,也不需要在函数中传self,但是被装饰的函数第一个参数需要是cls来表示自身类.可以用来调 ...
- Python @classmethod和@staticmethod装饰器使用介绍
@classmethod和@staticmethod装饰器使用介绍 by:授客 QQ:1033553122 简介 静态方法:类中用 @staticmethod装饰的不带 self 参数的方法.类的静态 ...
- django classonlymethod 和 python classmethod的区别
--classmethod可以被一个实例调用,classonlyethod只能被类调用 class Kls(object): no_inst = 0 def __init__(self): Kls.n ...
随机推荐
- Android笔记(二十一) Android中的Adapter
Android中有一些View是包含多个元素的,例如ListView,GridView等,为了给View的每一个元素都设置数据,就需要Adapter了. 常用的Adapter包括ArrayAdapte ...
- 基于numpy实现矩阵计算器
要求 制作一个Python的矩阵计算器: ① 程序提供任意两矩阵的加.乘法运算:方阵的行列式计算.逆矩阵计算.特征分解:任意矩阵的转置等计算功能,可自行添加功能 ② 从控制台通过键盘获取数据并完成以上 ...
- KVM虚拟机的管理
1. 查看KVM虚拟机配置文件及运行状态 (1) KVM虚拟机默认配置文件位置: /etc/libvirt/qemu/ autostart目录是配置kvm虚拟机开机自启动目录 (2) virsh命令 ...
- kubbernetes Flannel网络部署(五)
一.Flannel生成证书 1.创建Flannel生成证书的文件 [root@linux-node1 ~]# vim flanneld-csr.json { "CN": " ...
- python函数式编程-装饰器
在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator). 由于函数也是一个对象,而且函数对象可以赋值给变量,所以通过变量也能调用该函数. >>> def now() ...
- 关于zsh-autosuggestions插件导致粘贴内容很慢的问题
zsh开启autosuggestions 插件的时候,在终端中粘贴大量的内容的时候,会粘贴的很慢,基本上是一个字符一个字符的粘贴的. 解决方案 在.zshrc文件中配置以下内容: # This spe ...
- ArcGIS + Python 批量裁剪、添加X/Y坐标脚本
前言 前一段时间,同事拿来的数据范围太大,用不了那么多(只需要一个乡镇的,结果拿来区县的),太多了加载也是问题.所以就让我给处理下. 由于文件较多,手动裁剪的话,我一个一个用ArcGIS工具箱中的工具 ...
- 大数据之路week06--day07(Hadoop生态圈的介绍)
Hadoop 基本概念 一.Hadoop出现的前提环境 随着数据量的增大带来了以下的问题 (1)如何存储大量的数据? (2)怎么处理这些数据? (3)怎样的高效的分析这些数据? (4)在数据增长的情况 ...
- 22 webpack结合Vue使用的总结
总结梳理:webpack中如何使用vue: 1.安装vue的包:cnpm i vue -S 2.由于 在webpack中,推荐使用 .vue这个组件模板文件定义组件, 所以,需要安装 能解析这种文件的 ...
- pandas模块的基本用法
一.读取文件 import pandas as pd data = pd.read_csv("F:\\ml\\机器学习\\01\\score.csv") #一般读取的是csv文件, ...