Fluent Python: Classmethod vs Staticmethod
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的更多相关文章
- python @classmethod和@staticmethod区别
python 类方法和静态方法区别 python @classmethod和@staticmethod区别 Python中至少有三种比较常见的方法类型,即实例方法,类方法.静态方法.它们是如何定义的呢 ...
- python classmethod 和 staticmethod的区别
https://stackoverflow.com/questions/12179271/meaning-of-classmethod-and-staticmethod-for-beginner 1. ...
- Python @classmethod和@staticmethod装饰器使用介绍
@classmethod和@staticmethod装饰器使用介绍 by:授客 QQ:1033553122 简介 静态方法:类中用 @staticmethod装饰的不带 self 参数的方法.类的静态 ...
- python基础知识讲解——@classmethod和@staticmethod的作用
python基础知识讲解——@classmethod和@staticmethod的作用 在类的成员函数中,可以添加@classmethod和@staticmethod修饰符,这两者有一定的差异,简单来 ...
- (译文)Python中的staticmethod与classmethod
原文是stackoverflow的一则高票回答,原文链接 可能之前也有人翻译过,但是刚好自己也有疑惑,所以搬运一下,个人水平有限所以可能翻译存在误差,欢迎指正(如侵删). 尽管classmethod和 ...
- 洗礼灵魂,修炼python(47)--巩固篇—定义类的方法之@classmethod,@staticmethod
定义类的方法,相信你会说,不就是在class语句下使用def () 就是定义类的方法了嘛,是的,这是定义的方法的一种,而且是最普通的方式 首先,我们已经知道有两种方式: 1.普通方法: 1)与类无关的 ...
- python基础-abstractmethod、__属性、property、setter、deleter、classmethod、staticmethod
python基础-abstractmethod.__属性.property.setter.deleter.classmethod.staticmethod
- 【python】Python 中的 classmethod 和 staticmethod
Python 中的 classmethod 和 staticmethod 有什么具体用途? 推荐地址:http://www.cnblogs.com/wangyongsong/p/6750454.htm ...
- python的@classmethod和@staticmethod
本文是对StackOverflow上的一篇高赞回答的不完全翻译,原文链接:meaning-of-classmethod-and-staticmethod-for-beginner Python面向对象 ...
随机推荐
- RN如何固定底部的按钮
如上图的底部新增按钮,要是放在web里那是相当简单,直接是用固定定位就行,但是在RN里是没有固定定位可言的. 方案一: 采用绝对定位,相对于最外层的定位在底部位置.(在部分安卓机上有问题,动态计算的高 ...
- 竞赛题解 - Palisection(CF-17E)
Palisection(CF-17E) - 竞赛题解 Manacher学到一定程度,也需要练一下有趣的题了-- (这是多老的题了 \(QwQ\))[传送门] 『题意』 给出一个字符串,求总共有多少对不 ...
- 持续集成(CI – Continuous Integration)
持续集成(CI – Continuous Integration) 在传统的软件开发中,整合过程通常在每个人完成工作之后.在项目结束阶段进行.整合过程通常需要数周乃至数月的时间,可能会非常痛苦.持续集 ...
- 高级同步器:可重用的同步屏障Phaser
引自:https://shift-alt-ctrl.iteye.com/blog/2302923 在JAVA 1.7引入了一个新的并发API:Phaser,一个可重用的同步barrier.在此前,JA ...
- js扩展String.prototype.format字符串拼接的功能
1.题外话,有关概念理解:String.prototype 属性表示 String原型对象.所有 String 的实例都继承自 String.prototype. 任何String.prototype ...
- 4 二维数组中的查找 JavaScript
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- Jqgrid利用正则匹配表达式正确移除html标签
在使用JqGrid表格插件过程中,遇到一个问题:后台取出来的字段是带有Html标签的,于是将内容填充到表格之后,带有的html标签会把表格撑开或者每一行的内容显示不统一,导致非常难看,就像下图所示: ...
- centos配置NTP服务器
时间服务器: NTP(Network Time Protocol,网络时间协议)是用来使用网络中的各个计算机时间同步的一种协议,NTP服务器就是利用NTP协议提供时间同步服务的. 一.环境准备: 1. ...
- WPF的退出
很多时候,会自己写退出程序的代码. 比如,先显示登录框(LogIn),成功后隐藏它,并显示一个主窗体(MainWin),或者外部还调用了其他App,当你关闭MainWin不一定会直接退出整个程序的. ...
- [bzoj5278][Usaco2018 Open]Out of Sorts
有点厉害,,,不会啊 答案就是所有前i个数有多少不在前i个里的max? 为啥啊求助