Fluent Python一书9.4节比较了 Classmethod 和 Staticmethod 两个装饰器的区别:

给出的结论是一个非常有用(Classmethod), 一个不太有用(Staticmethod).

今天我们就对这两个装饰器做更深入的了解和比较,

(一) Classmethod:

(1)什么时候使用Classmethod?

classmethod最常见的用途是定义备选构造方法

(2)如何使用Classmethod?

下面我们用一个示例来展示如何使用classmethod,

假如我们设计了一个日期类:

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

显然这个类是可以用来存储日期的(不包含时区)

现在我们需要从格式"dd-mm-yyyy"的字符串创建很多Date类的实例,我们可能会在类外部先处理字符串,然后创建Date的实例:

string_date = "27-09-2017"
day, month, year = map(int, string_date.split('-'))
date1 = Date(day, month, year)

以上的方式可行,然而一个更为Pythonic的方式是使用classmethod:

class Date:
def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year @classmethod
def from_string(cls, string_date):
day, month, year = map(int, string_date.split('-'))
return cls(day, month, year)

在上面的Code里,from_string() 方法可以看作除了__init__之外的另一个构造方法,这个构造方法可以从日期格式字符直接创建实例:

string_date = "27-09-2017"
date2 = Date.from_string(string_date)

对于以上的Date类实现,我们需要看到classmethod装饰器的三个优点:

(a) 日期格式字符串处理是在一个地方,是可重用的

(b)比起在Date类外实现日期格式字符串处理,这里的封装更符合面向对象思想

(c)对于Date类可能有的子类,他们自动继承了from_string()方法

(二) Staticmethod:

(1)什么时候使用Staticmethod?

我从未见过不得不用staticmethod的情况, 如果想定义不需要与类交互的函数,那么在模块中定义也是完全可以的

(2)如何使用Staticmethod?

假如我们设计了一个Server类,有地址和端口两个属性:

class Server:
def __init__(self, ip_address, port):
self.ip_address = ip_address
self.port = port

现在我需要一个函数检查用户输入的是否是一个ipv4地址,这就可以用staticmethod来实现,因为检查ipv4地址的合法性和类本身并不需要交互:

import re

class Server:
def __init__(self, ip_address, port):
self.ip_address = ip_address
self.port = port @staticmethod
def is_ipv4(ip_string):
p = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$')
if p.match(ip_string):
return True
else:
return False

那么在该Server类中,只要涉及到检查ipv4的地方,我们都可以用到这个is_ipv4()方法了

其实这个方法也完全可以定义在模块里,效果是一样的

最后我们回到Fluent Python一书中对classmethod和staticmetho在行为上做的对比:

书中定义了Demo类,实现了一个classmethod,一个staticmethod:

class Demo:
@classmethod
def classmethod_demo(*args):
return args @staticmethod
def staticmethod_demo(*args):
return args

然后我们在控制台观察输出:

>>> import Example9_4
<Example9_4.Demo object at 0x7fd0b6dd6cf8>
>>> Example9_4.Demo.classmethod_demo()
(<class 'Example9_4.Demo'>,)
>>> Example9_4.Demo.staticmethod_demo()
()
>>> Example9_4.Demo.classmethod_demo('foo')
(<class 'Example9_4.Demo'>, 'foo')
>>> Example9_4.Demo.staticmethod_demo('foo')
('foo',)

我们可以看到无论怎么调用classmethod,第一个参数总是类名Demo,而staticmethod的行为与普通的函数类似。

Fluent Python: Classmethod vs Staticmethod的更多相关文章

  1. python @classmethod和@staticmethod区别

    python 类方法和静态方法区别 python @classmethod和@staticmethod区别 Python中至少有三种比较常见的方法类型,即实例方法,类方法.静态方法.它们是如何定义的呢 ...

  2. python classmethod 和 staticmethod的区别

    https://stackoverflow.com/questions/12179271/meaning-of-classmethod-and-staticmethod-for-beginner 1. ...

  3. Python @classmethod和@staticmethod装饰器使用介绍

    @classmethod和@staticmethod装饰器使用介绍 by:授客 QQ:1033553122 简介 静态方法:类中用 @staticmethod装饰的不带 self 参数的方法.类的静态 ...

  4. python基础知识讲解——@classmethod和@staticmethod的作用

    python基础知识讲解——@classmethod和@staticmethod的作用 在类的成员函数中,可以添加@classmethod和@staticmethod修饰符,这两者有一定的差异,简单来 ...

  5. (译文)Python中的staticmethod与classmethod

    原文是stackoverflow的一则高票回答,原文链接 可能之前也有人翻译过,但是刚好自己也有疑惑,所以搬运一下,个人水平有限所以可能翻译存在误差,欢迎指正(如侵删). 尽管classmethod和 ...

  6. 洗礼灵魂,修炼python(47)--巩固篇—定义类的方法之@classmethod,@staticmethod

    定义类的方法,相信你会说,不就是在class语句下使用def () 就是定义类的方法了嘛,是的,这是定义的方法的一种,而且是最普通的方式 首先,我们已经知道有两种方式: 1.普通方法: 1)与类无关的 ...

  7. python基础-abstractmethod、__属性、property、setter、deleter、classmethod、staticmethod

    python基础-abstractmethod.__属性.property.setter.deleter.classmethod.staticmethod

  8. 【python】Python 中的 classmethod 和 staticmethod

    Python 中的 classmethod 和 staticmethod 有什么具体用途? 推荐地址:http://www.cnblogs.com/wangyongsong/p/6750454.htm ...

  9. python的@classmethod和@staticmethod

    本文是对StackOverflow上的一篇高赞回答的不完全翻译,原文链接:meaning-of-classmethod-and-staticmethod-for-beginner Python面向对象 ...

随机推荐

  1. LeetCode 中级 - 重新排序得到的幂(105)

    从正整数 N 开始,我们按任何顺序(包括原始顺序)将数字重新排序,注意其前导数字不能为零. 如果我们可以通过上述方式得到 2 的幂,返回 true:否则,返回 false. 示例 1: 输入:1 输出 ...

  2. pom.xml文件报MavenArchiver错误 org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.maven.project.MavenProject, org.apache.maven.archiver.MavenArchiveConfiguration)

    第一种方式 war项目 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId> ...

  3. 【NXP开发板应用—智能插排】3.驱动GPIO点亮外接LED

    [前言] 首先感谢深圳市米尔科技有限公司举办的这次活动并予以本人参加这次活动的机会,以往接触过嵌入式,但那都是皮毛,最多刷个系统之类的,可以说对于嵌入式系统开发这件事情是相当非常陌生的,这次活动为我提 ...

  4. usb之鼠标作为按键输入

    1. 首先搞清楚,鼠标点左键.右键等能得到什么数据,然后分析这些数据上报事件即可. 第一个基本点:usb_alloc_urb函数,创建一个struct urb结构体,只能使用这个函数来创建,它是urb ...

  5. Leecode刷题之旅-C语言/python-344反转字符串

    /* * @lc app=leetcode.cn id=344 lang=c * * [344] 反转字符串 * * https://leetcode-cn.com/problems/reverse- ...

  6. UDP server Code

    Code Example: The following programs demonstrate the use of getaddrinfo(), gai_strerror(), freeaddri ...

  7. Fedora 下面安装FTP服务

    1. yum install vsftpd 2. systemctl disable vsftpd.service 3. systemctl stop vsftpd.service 4. system ...

  8. 推荐 的FPGA设计经验(1)组合逻辑优化

    主要内容摘自Quartus prime Recommended Design Practices For optimal performance, reliability, and faster ti ...

  9. 搭建Git服务器-SCM-Manager

    基于配置简单的原则,先试用一下SCM-Manager http://www.scm-manager.org/ 看主页介绍:Very easy installation 安装简单,配置方便,不需要额外的 ...

  10. 3668: [Noi2014]起床困难综合症

    3668: [Noi2014]起床困难综合症 https://www.lydsy.com/JudgeOnline/problem.php?id=3668 分析: 每一位分开考虑. 算出每一位为1,计算 ...