python classmethod 与 staticmethod

测试环境:

python3.7.9
vscode + Pylance

一、类变量与实例变量:

实例变量就是__init__函数初始化中的变量

而类变量类似于C++中的静态成员变量。

class Dog:
    dogbook = {
     '黄色':0,'白色':0,'黑色':0}
    def __init__(self,name,color,weight) -> None:
        self.name = name
        self.color = color
        self.weight = weight

dogbook是类变量
name、color、weight是实例变量

二、实例方法:

最常使用的就是实例方法

class Dog:
    def __init__(self,name,color,weight) -> None:
        self.name = name
        self.color = color
        self.weight = weight
        Dog.dogbook[color]+=1

    def bark(self):
        print("{}叫了起来".format(self.name))

dog1 = Dog("大黄","黄色","10kg")
dog1.bark()

特点:

  • 1、必须通过实例来调用
  • 2、定义时第一个参数必须是self
  • 3、可以使用类名访问类变量

三、静态方法(staticmethod)

以@staticmethod标识

  • 与普通的函数作用相同,仅仅是放在类中便于维护和理解
  • 可以通过实例调用或类名调用
    类似C++中的静态成员函数
class Dog:
    dogbook = {
     '黄色':0,'白色':0,'黑色':0}
    def __init__(self,name,color,weight) -> None:
        self.name = name
        self.color = color
        self.weight = weight
    @staticmethod
    def emotion():
        print("小狗们很开心")

dog1 = Dog("大黄","黄色","10kg")
dog1.emotion()
Dog.emotion()

四、类方法(classmethod)

需要用@classmethod标识

class Dog:
    dogbook = {
     '黄色':0,'白色':0,'黑色':0}
    def __init__(self,name,color,weight) -> None:
        self.name = name
        self.color = color
        self.weight = weight
    def bark(self):
        print("{}叫了起来".format(self.name))
    @classmethod
    def total_number(cls):
        total = sum(cls.dogbook.values())
        print("共有{}条狗狗".format(total))

dog1 = Dog("大黄","黄色","10kg")
dog1.bark()
Dog.total_number()
dog1.total_number()

总结:

  • 定义时必须以cls为第一个参数
  • 可以通过实例调用或类名调用

其实classmethod的功能很多都可以由其它方法实现。
比如前面的,cls.func()可以用Dog.func()代替

但classmethod中引入的cls参数具有类似多态的作用:
它会自动判断是调用的哪一个子类(基类)的函数

class Dog:
    color = "黄色、白色和黑色"
    dogbook = {
     '黄色':0,'白色':0,'黑色':0}
    def __init__(self,name,color,weight) -> None:
        self.name = name
        self.color = color
        self.weight = weight
        Dog.dogbook[color]+=1
    @classmethod
    def showColor(cls):
        print("这是{}的狗狗".format(cls.color))

class YellowDog(Dog):
    color = '黄色'
    def __init__(self, name, weight) -> None:
        super().__init__(name, "黄色", weight)

class BlackDog(Dog):
    color = '黑色'
    def __init__(self, name, weight) -> None:
        super().__init__(name, "黑色", weight)
class WhiteDog(Dog):
    color = '白色'
    def __init__(self, name, weight) -> None:
        super().__init__(name, "白色", weight)

dogs = [YellowDog("大黄",12),BlackDog("二黑",23),WhiteDog("小白",12)]
for dog in dogs:
    dog.showColor()

这样就不需要在子类中重写showColor方法,利用多态&继承实现了代码复用。

以上的@classmethod等修饰符,在我的测试中不加也是可以的。
其实很明显:这几种方法是靠self和cls来实现的。只需要把self和cls看作是类的成员变量(并且是保留字,不会和用户的自定义变量产生冲突),这几种方法没有本质区别。并且完全不需要用修饰符来区分。

但我翻阅的博客均加上了修饰符,兼容起见,还是加上这个修饰符比较好。

你可能感兴趣的:(python,python,多态)