@staticmethod装饰器的作用

121 阅读3分钟

@staticmethod

该装饰器可以讲类中的方法转为静态方法,以people类为例

为什么要有@staticmethod装饰器

class people:
    def eat(self):
        print("我要开始吃东西了~")

在正常情况下,如果我们想要使用eat方法,必须先实例化这个类。例如这样

P = people()
P.eat()

但是有些时候,我们并不像实例化这个类,因为用不到这个类,仅仅想要用到这个方法,为了一口醋而包一顿饺子明显是不好的,但是如果我们正常编写类的情况下,你会发现不进行实例化,直接调用,会出现如下结果:

class people:
    def eat(self):
        print("我要开始吃东西了~")
people.eat()
# output: TypeError: people.eat() missing 1 required positional argument: 'self'

那么如果我们想不进行实例化就调用这个函数呢?这个时候就要用到@staticmethod这个python自带的装饰器了。

@staticmethod装饰器的使用

将eat方法添加@staticmethod装饰器

class people:
    @staticmethod
    def eat():
        print("我要开始吃东西了~")
people.eat()
# output: 我要开始吃东西了~

可以看到,程序正常运行了,所以在这里就可以看出来,@staticmethod的核心作用就是可以实现不创造一个新对象的情况下调用这个方法
基本上到这里就已经明确了staticmethod的核心作用了,但是还有一些小的细节,可能让我们在后面使用时会产生一些理解不清楚,在这里也做一个简要的批注

staticmethod装饰的方法子类能否使用?

答案是:如果子类没有,会自动调用父类,子类存在,则以子类为准

class people:
    @staticmethod
    def eat():
        print("人要吃东西")
    @staticmethod
    def run():
        print("人在奔跑")
    @staticmethod
    def work():
        print("人在工作")

class Student(people):
    @staticmethod
    def run():
        print("学生在奔跑")
    def work(self):
        print("学生在学习")

if __name__ == "__main__":
    # 检查子类还能否正常调用父类的方法
    Student.eat()
    # 检查当子类和父类都存在的情况下,用的是谁的
    Student.run()
    # 检查当子类没有静态装饰,父类静态装饰,能否不报错
    Student.work()

打印结果如下:

TypeError: Student.work() missing 1 required positional argument: 'self'
人要吃东西
学生在奔跑

弊端1: 无法使用self

首先,使用staticmethod装饰的函数,是不需要self参数的,因为它是独立与类之外的(不用实例化就可以使用,self只有在实例化之后才能存在,而且默认作为类方法的第一个参数),staticmethod可以有参数,但是不会再存在实例化之后,第一个参数表示的类本身,这也就导致了,无法调用对象的内容。

class people:
    def __init__(self):
        self.name = "张三"
        self.age = 18

    @staticmethod
    def eat(self):
        """这里的self只是一个参数名称"""
        print(f"{self.name}在吃饭")
    def run(a):
        """self不是固定的参数名称,只是一种书写规范,类方法的第一个参数代表类本身,可以是任何名称"""
        print(f"{a.name}在奔跑")
# people.eat(18)  # 这里会报错
P = people()
P.run()

弊端2: 不使用staticmethod装饰也不是不能实现静态方法

class people:
    def __init__(self):
        self.name = "张三"
        self.age = 18


    def eat(self):
        print(f"{self}在吃饭")
people.eat("张三")

最开始我以为这种方法会报错,但是实际测试后发现,竟然可以正常运行?可能这也跟Python是一个动态语言,不限制参数类型有关系吧。