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

Python面向对象编程中,类中定义的方法可以是@classmethod 装饰的类方法,也可以是@staticmethod 装饰的静态方法,用的最多的还是不带装饰器的实例方法。为方便,在下文中用@classmethod装饰的类方法将直接用@classmethod来表述,@staticmethod同理,望读者在阅读时自行加以区分。

@classmethod和@staticmethod很相似,它们装饰的方法在使用上只有一点区别:@classmethod装饰的方法第一个参数必须是一个类(通常为cls),而@staticmethod装饰的方法则按业务需求设置参数,也可以根本没有参数。

样例

样例是一个处理日期信息的类,如下:

  1. class Date(object):
  2. def __init__(self, day=0, month=0, year=0):
  3. self.day = day
  4. self.month = month
  5. self.year = year

这个类可以用来存储指定日期(不包括时区信息,假设所有日期都是UTC时间)。

这个类有一个__init__函数用来初始化实例对象,它的第一个必须的参数self指向一个已创建的Date类的实例对象,这个方法是一个典型的实例方法。

Class Method

有些任务用@classmethod 可以很好地完成。

假设我们要从一堆有着特定日期格式的字符串(如'dd-mm-yyyy')创建很多对应的Date类的实例,而且在项目的各个地方都要进行这样的转换。那么我们要做的是:

1. 解析一个字符串来得到day,month,year这三个整数变量或者组装出一个tuple

2. 把这些值传递给初始化函数来实例化Date实例对象

比如:

  1. day, month, year = map(int, string_date.split('-'))
  2. date1 = Date(day, month, year)

要实现这个目的,C++可以使用重载,但是Python没有这样的语法,但是可以使用@classmethod来实现,如下:

  1. @classmethod
  2. def from_string(cls, date_as_string):
  3. day, month, year = map(int, date_as_string.split('-'))
  4. date1 = cls(day, month, year)
  5. return date1
  6. date2 = Date.from_string('11-09-2012')

仔细比较这两种方法,使用@classmethod有以下优点:

1. 我们只写了一个转换字符串的方法,而且这个方法是可重用的。

2. 把这个方法封装在类中,更紧密(也许你会认为可以写一个单独的函数去转换字符串,但是使用@classmethod更符合面向对象的思维)。

3. cls 是类本身的对象,而不是类的实例对象,这样的话继承自Date的对象都会有from_string这个方法。

Static Method

那么@staticmethod呢?其实它跟@classmethod非常相似,只是它没有任何必需的参数。

假设我们要去检验一个日期的字符串是否有效。这个任务与Date类相关,但是又不需要Date实例对象,在这样的情况下@staticmethod就可以派上用场了。如下:

  1. @staticmethod
  2. def is_date_valid(date_as_string):
  3. day, month, year = map(int, date_as_string.split('-'))
  4. return day <= 31 and month <= 12 and year <= 3999
  5. # usage:
  6. 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等等。

转载于:https://www.cnblogs.com/fengff/p/9587952.html

python的@classmethod和@staticmethod相关推荐

  1. python中classmethod与staticmethod的差异及应用

    类中三种函数的应用 #!/usr/bin/env python # -*- coding: utf-8 -*-class TClassStatic(object):def __init__(self, ...

  2. Python中classmethod与staticmethod区别

    classmethod:类方法 staticmethod:静态方法 在python中,静态方法和类方法都是可以通过类对象和类对象实例访问.但是区别是: @classmethod 是一个函数修饰符,它表 ...

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

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

  4. python知识:@classmethod和@staticmethod的异同

    1 说明 @staticmethod的意思就是将后面的函数转化成静态函数. 大多数情况,@classmethod和@staticmethod效果一样.但是那不是正题,正式作用是类工厂,如果有类继承关系 ...

  5. [转载] python staticmethod有什么意义_Python 中的 classmethod 和 staticmethod 有什么具体用途

    参考链接: Python staticmethod() >>> type(a1) example 2: class a(object): @classmethod def cm(cl ...

  6. [转载] python classmethod存在的意义_@classmethod和@staticmethod对初学者的意义?

    参考链接: Python classmethod() 尽管classmethod和staticmethod非常相似,但这两个实体的用法略有不同:classmethod必须将对类对象的引用作为第一个参数 ...

  7. python @classmethod 和 @staticmethod区别,以及类中方法参数cls和self的区别

    一.@classmethod 和 @staticmethod 1.staticmethod 作用:让类中的方法变成一个普通函数(普通函数没有绑定在任何一个特定的类或者实例上.所以与不需要对象实例化就可 ...

  8. @classmethod和@staticmethod对初学者的意义? [重复]

    本文翻译自:Meaning of @classmethod and @staticmethod for beginner? [duplicate] This question already has ...

  9. python中classmethod的用法_Python中的@classmethod是如何使用的?

    在写Python程序的时候,特别是实现类方法的时候,通常会用到@staticmethod和@classmethod两种装饰器(function decorator),那这两个装饰器有什么作用呢?在这篇 ...

最新文章

  1. pca主成分分析结果解释_SKLEARN中的PCA(Principal Component Analysis)主成分分析法
  2. web service 基础学习
  3. python怎么安装requests库-小白安装python的第三方库:requests库
  4. Azure Redis 系列之 Azure Redis部署
  5. c 对一个mysql数据库进行操作_用C语言操作MySQL数据库
  6. Java——网络编程三要素
  7. linux C 应用消息队列在两个进程间通信
  8. JDK5新版RMI编程指南
  9. ansible基本模块-copy
  10. Matlab语言标点说明
  11. 搭建云上博客——阿里云实验室 学习笔记
  12. /*CS5460_Note_1*/
  13. PHP是什么,其优势有哪些?
  14. 2023年上半年软考报考指南~
  15. 2.给 Proxmox VE换源
  16. discuz 如何去掉:导读-最新发表
  17. python使用SMTP发送qq/sina邮件
  18. IP地址,子网掩码,网关三者的关系和作用
  19. PHP中使用compact函数
  20. 【MySQL 8.0 OCP 1Z0-908认证考试】题库精讲--第五讲mysqlbinlog与mysqldump(下)

热门文章

  1. 为什么ABAP整型的1转成string之后,后面会多个空格 1
  2. html5能火多久,html5有多火?看完这个你就知道了!
  3. spring学习记录(一)
  4. iphone开蓝牙wifi上网慢_为啥我开锁总是比别人慢?
  5. 十字路口红绿灯plc程序_交通灯程序的最优化(西门子S7-200PLC为例)
  6. 谷歌翻译api_翻译:TensorFlow on Android APP 示例
  7. 推理计算过程_初中物理电学计算题第六讲:极值问题推理和限制条件
  8. php万年历上个月下个月,php 万年历
  9. 虚拟机vcenter如何增加磁盘_如何在家搭建一套自己的实验平台(10)iSCSI 共享存储...
  10. UE4学习-打包失败 缺失UE4Game二进制文件