@staticmethod的使用

2019年10月25日 / 14次阅读 / Last Modified 2019年10月30日
内置函数

在python中定义类的时候,我们可以给类中的函数冠以@staticmethod这个装饰器。从字面上看,这个装饰器就是静态函数的意思,它有什么意思?如何使用呢?(对于装饰器不懂的同学,请先移步学习:python装饰器

static有静止不动的意思,中文一般翻译为静态。

一般类中的函数,都是与对象绑定,其第1个参数习惯上都使用self这个名称(也可以使用别的名称),表示当此函数被调用的时候,对象自己会作为第1个参数(隐式地)传入。不过有趣的是,这些函数在被调用的时候,此对象并没有显式的出现在参数列表中。将对象自身作为第1个参数传入,是python解释器自动完成的动作。

>>> '-'.join('12345')
'1-2-3-4-5'

以上代码,调用了str对象的join函数,join函数的定义如下:

join(self, iterable, /)
    Concatenate any number of strings.

    The string whose method is called is inserted in between each given string.
    The result is returned as a new string.

    Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'

join函数的第1个参数是self,表示对象本身,按上文的示例代码,就是 '-' 这个str对象。不过写出来的代码,参数只有'12345',没有写出self参数。这里请仔细体会!

被@staticmethod装饰过的函数,就不再是一般的成员函数了,而是“静态函数”。这类函数在调用的时候:

  • (1)python解释器不会将对象作为第1个参数传入;
  • (2)不要通过对象来调用此类函数,要通过类来调用;
  • (3)因为没有对象传入,这类函数就无法获取与对象绑定的成员信息,也就是不能访问任何一个对象绑定的属性信息,只能通过类名来访问类变量(class variable),这也是第2点的原因,要用类来调用静态函数;
  • (4)此类函数,被封装在类中,只能在此类以及继承此类的范围内访问,外界不可访问,也是一种封装技术。

它是静止的,不会随不同的类和对象而发生变动,只会出现在类以及继承于此类的空间中。

class group():

    num = 0

    def __init__(self, sn):
        self.sn = sn
        group.num += 1

    @staticmethod
    def getTotal():
        return group.num


g1 = group('123')
g2 = group('124')
g3 = group('125')
print(group.getTotal())

这代代码执行结果如下:

$ python3 static.py
3

当然,不使用@staticmethod装饰器也能实现这个功能,本文主要讨论的不是如何实现某个什么功能,而是介绍@staticmethod的使用。

注意看定义在group类中的被@staticmethod装饰的函数getTotal,它没有self参数,它也不会去做 self.* 这一类的访问,它可以通过 group.num 来访问这个class variable,不过也不建议这么做。

写到这里,我觉得有必要把我对@staticmethod这个装饰器使用的理解说清楚:@staticmethod定义的函数,只存在此类或继承此类的空间(namespace)中,它不接受对象参数,因此它的最佳使用场景,就是为此类以及继承此类的类提供某种计算服务(比如某些属性值的检查),这类计算不需要具体对象的参与,也最好不要去访问类变量(在继承的情况下,类的名称会变),它的计算参数很可能均来自外部输入,但是计算结果为类和对象服务。或者,@staticmethod就是用一个类来封装一个功能块接口,如果没有继承,它们之间可以通过类名来相互调用。

官方对@staticmethod的说明中提到,“用来构建不同于__init__的对象创建函数”。这个很好理解(@classmethod也有此功能),但是只能在函数中,直接出现class name,否则就不能访问__init__函数,也就谈不上创建对象的功能了。

总之,个人感觉@staticmethod的应用不是特别广,因为只能显式调用class name,才能访问到一些参数,不如@classmethod那么灵活。不过,用来封装一组函数还是可以的,但是这种封装,是不是也不如直接使用一个.py(模块)来的更简单直接呢?可能只有继承这个特性,能够让@staticmethod装饰器,在某些时候,让代码更具有可读性吧。

为类和对象服务,但是参数全部由外部提供,从语义上适合放在类的内部,也需要这种封装的时候,请使用@staticmethod装饰器。

-- EOF --

本文链接:https://www.pynote.net/archives/1388

留言区

电子邮件地址不会被公开。 必填项已用*标注


前一篇:
后一篇:

More

麦新杰的Python笔记

Ctrl+D 收藏本页


©Copyright 麦新杰 Since 2019 Python笔记

go to top