python的@classmethod和@staticmethod

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

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

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

样例

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

  1. class Date(object):
  2.  
  3. def __init__(self, day=0, month=0, year=0):
  4. self.day = day
  5. self.month = month
  6. 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.  
  7. 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.  
  6. # usage:
  7. 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

时间: 2024-07-30 14:55:00

python的@classmethod和@staticmethod的相关文章

python类方法@classmethod与@staticmethod

目录 python类方法@classmethod与@staticmethod 一.@classmethod 介绍 语法 举例 二.@staticmethod 介绍 语法 举例 python类方法@classmethod与@staticmethod 一.@classmethod 介绍 与普通的类方法有所不同的是,用@classmethod修饰的类方法不传入self实例本身,而是传入cls,代表这个类自身,可以来调用类的属性,类的方法,实例化对象等. 语法 使用的语法也非常简单,直接在类方法上加上装

python中classmethod与staticmethod的差异及应用

类中三种函数的应用 #!/usr/bin/env python # -*- coding: utf-8 -*- class TClassStatic(object): def __init__(self, data): self.data = data def printself(*arg): # for item in arg: # print item.data print("printself: ", arg) @staticmethod def smethod(*arg): p

Python中classmethod与staticmethod区别

classmethod:类方法staticmethod:静态方法 在python中,静态方法和类方法都是可以通过类对象和类对象实例访问.但是区别是: @classmethod 是一个函数修饰符,它表示接下来的是一个类方法,而对于平常我们见到的则叫做实例方法. 类方法的第一个参数cls,而实例方法的第一个参数是self,表示该类的一个实例. 普通对象方法至少需要一个self参数,代表类对象实例 类方法有类变量cls传入,从而可以用cls做一些相关的处理.并且有子类继承时,调用该类方法时,传入的类变

粗解python的@classmethod和@staticmethod及普通实例方法

引言: 使用不同的函数定义方法,可以使得函数定义更加有效而且易于维护 本文为博主原创,根据本人自己的理解整理而成,若有不准确的地方,希望能留言告知以免误导他人: 首先进一段代码,来直观感受一下不同类型的函数的定义方法: >>> >>> class A(object): a = 1 def instance_method(self): print '实例方法打印类变量a: %s' % self.a @classmethod def class_method(cls): p

python的@classmethod和@staticmethod的区别和使用

@classmethod classmethod 修饰符对应的函数不需要实例化,不需要 self 参数,但第一个参数需要是表示自身类的 cls 参数,可以来调用类的属性,类的方法,实例化对象等. class A(object): bar = 1 def func1(self): print('foo') @classmethod def func2(cls): print('func2') print(cls.bar) cls().func1() # 调用 foo 方法 A.func2() #

Python的classmethod和staticmethod区别

静态方法(staticmethod) 类方法(classmethod) 静态方法和类方法都可以通过类名.方法名或者实例.方法访问. #-*- coding:utf8 -*- class A(object): def instance_method(self,x): print "instance_method (%s,%s)" % (self,x) @classmethod def class_method(cls,x): #类方法的调用使用类本身作为其隐含的参数 #调用者本身并不需要

@classmethod及@staticmethod方法浅析【python】

目前对于python中@classmethod 类方法和@staticmethod静态方法的有了一定的认识,之后有进一步的认识后继续记录. @classmethod :是和一个class类相关的方法,可以通过类货类实例进行调用,并将该class对象(不是class的实例对象)隐式地当作第一个参数传入. @staticmethod :基本上和一个全局函数差不多,可以通过类或者类的实例对象进行调用,不会隐式地传入任何参数. 区别 :类方法需要额外的类变量cls,调用类方法传入的类变量cls是子类,而

Python中@property和@classmethod和@staticmethod

前戏 首先,先要弄清楚一个类里面的,各个组成部分都应该怎么称呼. - 注:可能叫法会不太一样. 关于@property 顾名思义:它的意思为'属性'. 作用: 1:使用它你将会把类方法,变为类属性.并且是只读属性. 2:它会重新实现getter和setter方法. 看代码: class Person: def __init__(self,first_name,last_name): self.first_name = first_name self.last_name = last_name @

4月16日 python学习总结 封装之property、多态 、classmethod和staticmethod

一.封装之property @property把一个函数伪装成一个数据类型  @伪装成数据的函数名.setter   控制该数据的修改,修改该数据时触发 @伪装成数据的函数名.delect  控制该数据的删除,删除该数据时触发 class People: def __init__(self,name): self.__name=name @property #将name()函数伪装成一个数据属性name def name(self): #obj.name print('您现在访问的是用户名...