AYE89

coding & learning

导航

Python的 @staticmethod@classmethod方法

Posted on 2020-05-11 06:50  AYE89  阅读(174)  评论(0编辑  收藏  举报

1. 实例方法,类方法和静态方法

实例方法:需要绑定一个类的instance

类方法:绑定到类,影响该类所有instance (@classmethod)

静态方法:与类无关,相当于定义了一个局部域函数为该类专门服务,没什么其它用处。因为没绑定instance,所以不能修改instance的attribute。(@staticmethod)

 

2. 例子

我在类中一共定义了3个方法,m1 是实例方法,第一个参数必须是 self(约定俗成的)。m2 是类方法,第一个参数必须是cls(同样是约定俗成),m3 是静态方法,参数根据业务需求定,可有可无。

class A(object):
    def m1(self, n):
        print("self:", self)

    @classmethod
    def m2(cls, n):
        print("cls:", cls)

    @staticmethod
    def m3(n):
        pass

a = A()

 

调用实例方法:

A.m1(a, 1) # not recommended
a.m1(1)

A.m1是一个还没有绑定实例对象的方法,对于未绑定方法,调用 A.m1 时必须显示地传入一个实例对象进去,而 a.m1是已经绑定了实例的方法,python隐式地把对象传递给了self参数,所以不再手动传递参数,这是调用实例方法的过程。

 

调用类方法:

A.m2(1)
a.m2(1)  # both are equivalent

m2是类方法,不管是 A.m2 还是 a.m2,都是已经自动绑定了类对象A的方法,对于后者,因为python可以通过实例对象a找到它所属的类是A,找到A之后自动绑定到 cls。

 

调用静态方法:

A.m3(1)
a.m3(1)  # both are equivalent

m3是类里面的一个静态方法,跟普通函数没什么区别,与类和实例都没有所谓的绑定关系,它只不过是碰巧存在类中的一个函数而已。不论是通过类还是实例都可以引用该方法。

 

3. 使用场景

静态方法的使用场景
如果在方法中不需要访问任何实例方法和属性纯粹地通过传入参数并返回数据的功能性方法那么它就适合用静态方法来定义它节省了实例化对象的开销成本往往这种方法放在类外面的模块层作为一个函数存在也是没问题的而放在类中仅为这个类服务例如下面是微信公众号开发中验证微信签名的一个例子它没有引用任何类或者实例相关的属性和方法

 

类方法的使用场景有:

  • 作为工厂方法创建实例对象,例如内置模块 datetime.date 类中就有大量使用类方法作为工厂方法,以此来创建date对象。
class date:

    def __new__(cls, year, month=None, day=None):
        self = object.__new__(cls)
        self._year = year
        self._month = month
        self._day = day
        return self

    @classmethod
    def fromtimestamp(cls, t):
        y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
        return cls(y, m, d)

    @classmethod
    def today(cls):
        t = _time.time()
        return cls.fromtimestamp(t)

 

  • 如果希望在方法裡面调用静态类,那么把方法定义成类方法是合适的,因为要是定义成静态方法,那么你就要显示地引用类A,这对继承来说可不是一件好事情。
class A:

    @staticmethod
    def m1()
        pass

    @staticmethod
    def m2():
        A.m1() # bad usage

    @classmethod
    def m3(cls):
        cls.m1() # good usage