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. 19-3-1Python的PyCharm编辑器,以及格式化输出、while循环、运算符、编码初识

    第一次使用PyCharm,需要注意到是否使用的自己安装的python版本,或者使用的自带版本,如果使用的自带版本,注意切换. PyCharm使用优点,可以一步一步看程序的出错问题,即Debug的使用, ...

  2. MySQL Group Replication 搭建[Multi-Primary Mode]

    1. 环境准备 CentOS7.3 percona-server-5.7.18-14 两台服务器ip地址和主机名 10.0.68.206 yhjr-osd-mysql01-uat 10.0.68.20 ...

  3. CentOS 7.x eth0

    1:Test Environment [root@linux-node1 ~]# cat /etc/redhat-release Red Hat Enterprise Linux Server rel ...

  4. Spring security学习笔记(二)

    对比两种承载认证信息的方式: session vs token token验证方案: session验证方案: session即会话是将用户信息保存在服务端,根据请求携带的session_id,从服务 ...

  5. day 13 内置函数

    内置函数思维导图:https://www.processon.com/view/link/5c13ad2de4b0ed122da75668 内置函数 作用域相关:   locals() 返回当前作用域 ...

  6. S3C2440上LCD驱动(FrameBuffer)实例开发讲解(一)

    一.开发环境 主  机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand, Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2 二.背景知识 ...

  7. S3C2440启动程序运行过程

    s3c2440有两种启动方式,一种Nor flash 启动,一种Nand flash 启动. 由于NAND FLASH是接在NAND FLASH控制器上而不是系统总线上,所以没有在S3C2440A的8 ...

  8. 动态链接库函数内的静态变量,奇妙的UNIQUE Bind

    title: 动态链接库函数内的静态变量,奇妙的UNIQUE Bind date: 2018-09-28 09:28:22 tags: --- 介绍 模板函数和内敛函数中的静态变量,在跨so中的表现, ...

  9. break和continue使用

    前面讲的循环,这里就是控制循环的东西 break其实在我们学习switch判断的时候就是用到了 break:代表跳出整个循环 continue和break的用法差不多 continue:代表只跳出当前 ...

  10. 笔记-jinja2语法

    笔记-jinja2语法 1.      基本语法 控制结构 {% %} 变量取值 {{ }} 注释 {# #} 2.      变量 最常用的是变量,由Flask渲染模板时传过来,比如上例中的”nam ...