python的@classmethod和@staticmethod
本文是对StackOverflow上的一篇高赞回答的不完全翻译,原文链接:meaning-of-classmethod-and-staticmethod-for-beginner
Python面向对象编程中,类中定义的方法可以是@classmethod 装饰的类方法,也可以是@staticmethod 装饰的静态方法,用的最多的还是不带装饰器的实例方法。为方便,在下文中用@classmethod装饰的类方法将直接用@classmethod来表述,@staticmethod同理,望读者在阅读时自行加以区分。
@classmethod和@staticmethod很相似,它们装饰的方法在使用上只有一点区别:@classmethod装饰的方法第一个参数必须是一个类(通常为cls),而@staticmethod装饰的方法则按业务需求设置参数,也可以根本没有参数。
样例
样例是一个处理日期信息的类,如下:
- class Date(object):
- def __init__(self, day=0, month=0, year=0):
- self.day = day
- self.month = month
- self.year = year
这个类可以用来存储指定日期(不包括时区信息,假设所有日期都是UTC时间)。
这个类有一个__init__函数用来初始化实例对象,它的第一个必须的参数self指向一个已创建的Date类的实例对象,这个方法是一个典型的实例方法。
Class Method
有些任务用@classmethod 可以很好地完成。
假设我们要从一堆有着特定日期格式的字符串(如'dd-mm-yyyy')创建很多对应的Date类的实例,而且在项目的各个地方都要进行这样的转换。那么我们要做的是:
1. 解析一个字符串来得到day,month,year这三个整数变量或者组装出一个tuple
2. 把这些值传递给初始化函数来实例化Date实例对象
比如:
- day, month, year = map(int, string_date.split('-'))
- date1 = Date(day, month, year)
要实现这个目的,C++可以使用重载,但是Python没有这样的语法,但是可以使用@classmethod来实现,如下:
- @classmethod
- def from_string(cls, date_as_string):
- day, month, year = map(int, date_as_string.split('-'))
- date1 = cls(day, month, year)
- return date1
- date2 = Date.from_string('11-09-2012')
仔细比较这两种方法,使用@classmethod有以下优点:
1. 我们只写了一个转换字符串的方法,而且这个方法是可重用的。
2. 把这个方法封装在类中,更紧密(也许你会认为可以写一个单独的函数去转换字符串,但是使用@classmethod更符合面向对象的思维)。
3. cls 是类本身的对象,而不是类的实例对象,这样的话继承自Date的对象都会有from_string这个方法。
Static Method
那么@staticmethod呢?其实它跟@classmethod非常相似,只是它没有任何必需的参数。
假设我们要去检验一个日期的字符串是否有效。这个任务与Date类相关,但是又不需要Date实例对象,在这样的情况下@staticmethod就可以派上用场了。如下:
- @staticmethod
- def is_date_valid(date_as_string):
- day, month, year = map(int, date_as_string.split('-'))
- return day <= 31 and month <= 12 and year <= 3999
- # usage:
- is_date = Date.is_date_valid('11-09-2012')
从上面的用法可以看出,它只是一个功能,调用的语法和一般的方法调用一样,也不访问实例对象那和它的内部字段和方法。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
以下有错误的地方
类的普通方法
class Animal(object):
def __init__(self,name):
self.name = name
def intro(self):
print('there is a %s'%(self.name))
cat = Animal('cat')
cat.intro()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
静态类方法
class Animal(object):
def __init__(self,name):
self.name = name
@staticmethod
def intro(self):
print('there is a %s'%(self.name))
cat = Animal('cat')
cat.intro()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
加上装饰器后运行会报错,原因是方法变为一个普通函数,脱离的与类的关系,不能引用构造函数中的变量了。
使用场景举例:python内置方法os中的方法,可以直接使用的工具包,跟类没关系。
class Animal(object):
def __init__(self,name):
self.name = name
@classmethod
def intro(self):
print('there is a %s'%(self.name))
cat = Animal('cat')
cat.intro()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
报错信息
如果换成
class Animal(object):
name = 'cat'
def __init__(self,name):
self.name = name
@classmethod
def intro(self):
print('there is a %s'%(self.name))
cat = Animal('cat')
cat.intro()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
可以正常运行。
结论:类方法只能调用类变量,不能调用实例变量
属性方法@property 把一个方法变为(伪装成)类属性。因为类属性的实质是一个类变量,用户可以调用变量就可以修改变量。某些特定场景要限制用户行为,就用到静态方法。
@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性。(摘自廖雪峰的博客)
class Animal(object):
def __init__(self,name):
self.name = name
@property
def intro(self,food):
print('there is a %s eating %s'%(self.name,food))
cat = Animal('cat')
cat.intro()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
报错:
方法不能正常调用。如果要调用,如下:
cat.intro
- 1
但是这样的话,方法就没办法单独传入参数。如果要传入参数,如下:
class Animal(object):
def __init__(self,name):
self.name = name
@property
def intro(self):
print('there is a %s eating %s'%(self.name,food))
@intro.setter
def intro(self,food):
pass
cat = Animal('cat')
cat.intro
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
cat.intro还有其他操作getter deleter等等。
python的@classmethod和@staticmethod的更多相关文章
- python类方法@classmethod与@staticmethod
目录 python类方法@classmethod与@staticmethod 一.@classmethod 介绍 语法 举例 二.@staticmethod 介绍 语法 举例 python类方法@cl ...
- Python中classmethod与staticmethod区别
classmethod:类方法staticmethod:静态方法 在python中,静态方法和类方法都是可以通过类对象和类对象实例访问.但是区别是: @classmethod 是一个函数修饰符,它表示 ...
- 粗解python的@classmethod和@staticmethod及普通实例方法
引言: 使用不同的函数定义方法,可以使得函数定义更加有效而且易于维护 本文为博主原创,根据本人自己的理解整理而成,若有不准确的地方,希望能留言告知以免误导他人: 首先进一段代码,来直观感受一下不同类型 ...
- Python中classmethod和staticmethod的区别
学习python中经常会出现一些相近或者相似的语法模块等,需要对比分析才能加深记忆,熟练运用. staticmethod:静态方法 classmethod:类方法 在python中,静态方法和类方法都 ...
- Python的classmethod和staticmethod区别
静态方法(staticmethod) 类方法(classmethod) 静态方法和类方法都可以通过类名.方法名或者实例.方法访问. #-*- coding:utf8 -*- class A(objec ...
- python基础知识讲解——@classmethod和@staticmethod的作用
python基础知识讲解——@classmethod和@staticmethod的作用 在类的成员函数中,可以添加@classmethod和@staticmethod修饰符,这两者有一定的差异,简单来 ...
- @classmethod及@staticmethod方法浅析【python】
目前对于python中@classmethod 类方法和@staticmethod静态方法的有了一定的认识,之后有进一步的认识后继续记录. @classmethod :是和一个class类相关的方法, ...
- 洗礼灵魂,修炼python(47)--巩固篇—定义类的方法之@classmethod,@staticmethod
定义类的方法,相信你会说,不就是在class语句下使用def () 就是定义类的方法了嘛,是的,这是定义的方法的一种,而且是最普通的方式 首先,我们已经知道有两种方式: 1.普通方法: 1)与类无关的 ...
- python基础-abstractmethod、__属性、property、setter、deleter、classmethod、staticmethod
python基础-abstractmethod.__属性.property.setter.deleter.classmethod.staticmethod
随机推荐
- noj1475(递推题)统计多少个1
http://acm.nbut.cn/Problem/view.xhtml?id=1475 题意:给出一个数,需要你统计在这个数范围内有多少个1........ 思路:从高位到低位计算,例如1312 ...
- spring配置:context:property-placeholder 读取配置文件信息 在配置文件中使用el表达式填充值
spring将properties文件读取后在配置文件中直接将对象的配置信息填充到bean中的变量里. 原本使用PropertyPlaceholderConfigurer类进行文件信息配置.Prope ...
- [Linux]gcc/libc/glibc
转自:http://blog.csdn.net/weiwangchao_/article/details/16989713 1.gcc(gnu collect compiler)是一组编译工具的总称. ...
- BlueZ--内核层+应用层
BlueZ 1.Kernel层实现: bluetooth协议栈有多层结构,最底层的硬件协议在硬件中就已经实现了.软件级别的协议实现,从HCI这一层开始实现. BlueZ对各层协议的实现是依托于Sock ...
- C语言错误: CRT detected that the application wrote to memory after end of heap buffer
CRT detected that the application wrote to memory after end of heap buffer 多是中间对其进行了一些操作,在程序结束处,释放内存 ...
- e2fsprogs 移植
e2fsprogs是用维护ext2,ext3和ext4文件系统的工具程序集.检测和修复文件系统,需要用到其中的fsck, ext2fs等工具, 由于开发板上没有,重新制作文件系统又比较麻烦.所以就需要 ...
- PHPExcel IE导出乱码问题
引用改网站介绍:http://blog.chinaunix.net/uid-22414998-id-113450.html PHPExcel是微软认证的一个PHP操作Excel表格的类库,功能强大,所 ...
- ThinkPHP无限级分类
<?php // +---------------------------------------------------------------------- // | ThinkPHP [ ...
- 使用webdriverwait封装查找元素方法
对于selenium原生的查找元素方法进行封装,在timeout规定时间内循环查找页面上有没有某个元素 这样封装的好处: 1.可以有效提高查找元素的效率,避免元素还没加载完就抛异常 2.相对于time ...
- Laravel5.1 关联模型之后操作
之前写过关于模型关联的笔记,但是模型关联好后的一些使用没有介绍,今天补上 1 写入关联模型 1.1 使用Save方法(一对多) 我们准备了两个模型:Post和Comment. 它们的关系是一对多关系. ...