Python3 @staticmethod 函数装饰器 声明一个类静态方法
@staticmethod
函数装饰器的主要作用是将一个类的普通方法(需要实例化使用)声明为一个类的静态方法(可以直接使用类名调用)。一般建议在使用staticmethod的时候最好不要与类中的其他成员关联,因为它在调用类的其他成员时必须要硬编码类名,也就是要显式的写出类名,如果类名发生改变会出现严重的问题,并且在类的重载上也经历不要重载静态方法,同样也是硬编码导致的问题。 它是Python的内置函数,在python文件中直接可以使用。它只能被应用在类(class)中。
语法
class main:
@staticmethod
def run(arg1, arg2, ...):
...
参数
arg1,arg2 - 自定义参数
实例
§ 实例1 - @staticmethod的使用方法
代码及运行结果:
#先声明类
class main:
#普通方法
def set(self, x):
print(x)
#类方法
@staticmethod
def run(n):
print(n)
#普通方法需要实例化后才能调用
o = main()
o.set('abc')
#输出
abc
#类方法可以直接使用,不需要实例化
main.run(123)
#输出
123
§ 实例2 - @staticmethod的使用场景之代码整合
这个例子是配合@classmethod一起使用的,如果没有看过@classmethod的话,可以先去浏览一起它的实例2。
代码及运行结果:
#创建一个类
class Date(object):
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def print_date(self):
print(self.year, self.month, self.day)
#声明类方法
@classmethod
def from_string(cls, date_as_string):
year, month, day = map(int, date_as_string.split('-'))
return cls(year, month, day) #实例化类并返回实例化对象
data_object = Date.from_string('2018-10-31')
#执行输出函数
data_object.print_date()
2018 10 31
#在用户使用“-”作为分隔符的时候,是正确的,可是用户的行为是很难预判的,他们有可能用“/”或者“_”作为分隔符。那么程序就无法正常执行了。我们需要一个智能的分配机制。代码如下:
#引入正则包
import re
class Date(object):
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def print_date(self):
print(self.year, self.month, self.day)
#声明类方法
@classmethod
def from_string(cls, date_as_string, space):
year, month, day = map(int, date_as_string.split(space))
return cls(year, month, day) #实例化类并返回实例化对象
#声明静态方法
@staticmethod
def check_space(date_as_string):
#这个正则只是为了演示分割符号的获取,所以没有过多的去考虑数字以及2个分割是否正确。
return re.match(r'\d+(.)\d+(.)\d+', date_as_string).groups()[0]
space = Date.check_space('2018/10/31')
#打印一下分隔符为"/"
print(space)
data_object = Date.from_string('2018/10/31', space)
#执行输出函数
data_object.print_date()
2018 10 31
§ 实例3 - @staticmethod注意事项之类的重载
由于staticmethod在调用类成员的时候,需要硬编码类名称,所以在一些类成员发生改变的时候,会出现一些问题。请看下面的代码:
#声明一个类
class main:
#声明run静态方法
@staticmethod
def run():
#调用name静态方法
main.name()
#声明name静态方法
@staticmethod
def name():
print('我是main类的name方法')
#声明子类并继承main类
class main2(main):
#重载基类的name方法
@staticmethod
def name():
print('我是main2类的name方法')
#由于子类继承了基类,所有我们可以用子类的名称调用基类的name方法。
main2.run()
#我是main类的name方法
#输出结果却是基类的name方法,视乎重载是没有用的。事实上并不是没用,我们来尝试直接调用一下子类的name方法。
main2.name()
#我是main2类的name方法
#输出的结果正确,确定是已经重载了基类的name方法。那么为什么调用run方法不行的呢?是因为run方法中硬编码了基类的名称。所有无论被继承到那里,它永远调用的都是基类的name方法。这是需要注意的地方。但是@classmethod装饰器并不会这样,因为@classmethod的一个参数是指向当前调用类的。
#具体的可以查看一下@classmethod的第三个实例。
#所以建议使用@staticmethod声明的方法应该是一个完全的不涉及其他类成员的功能方法,如果涉及类内部成员的调用建议使用@classmethod。