Python classmethod()

classmethod() 方法返回给定函数的类方法。

示例

class Student:
  marks = 0

  def compute_marks(cls, obtained_marks):
    cls.marks = obtained_marks
    print('Obtained Marks:', cls.marks)

# convert compute_marks() to class method Student.print_marks = classmethod(Student.compute_marks)
Student.print_marks(88) # Output: Obtained Marks: 88

classmethod() 语法

classmethod() 方法的语法是

classmethod(function)

classmethod() 被认为是“不符合 Python 风格的”,因此在较新的 Python 版本中,你可以使用 @classmethod 装饰器 来定义类方法。

语法是

@classmethod
def func(cls, args...)

classmethod() 参数

classmethod() 方法接受一个参数

  • function - 需要转换为类方法的函数

classmethod() 返回值

classmethod() 方法返回给定函数的类方法。


什么是类方法?

类方法是绑定到类而不是其对象的方法。它不需要创建类实例,很像静态方法。

静态方法和类方法之间的区别是

  • 静态方法对类一无所知,只处理参数
  • 类方法与类一起工作,因为它的参数始终是类本身。

类方法可以由类及其对象调用。

Class.classmethod()
Or even
Class().classmethod()

但无论如何,类方法总是附属于一个类,其第一个参数是类本身 cls

def classMethod(cls, args...)

示例 1:使用 classmethod() 创建类方法

class Person:
    age = 25

    def printAge(cls):
        print('The age is:', cls.age)

# create printAge class method Person.printAge = classmethod(Person.printAge)
Person.printAge()

输出

The age is: 25

这里,我们有一个类 Person,其中一个成员变量 age 赋值为 25。

我们还有一个函数 printAge,它接受一个参数 cls,而不是我们通常使用的 self

cls 接受类 Person 作为参数,而不是 Person 的对象/实例。

现在,我们将方法 Person.printAge 作为参数传递给函数 classmethod。这会将方法转换为类方法,以便它接受第一个参数作为类(即 Person)。

在最后一行中,我们调用 printAge 而不创建 Person 对象,就像我们对静态方法所做的那样。这会打印类变量 age


你何时使用类方法?

1. 工厂方法

工厂方法是那些针对不同用例返回类对象(如构造函数)的方法。

它类似于 C++ 中的函数重载。由于 Python 没有这样的功能,所以使用类方法和静态方法。

示例 2:使用类方法创建工厂方法

from datetime import date

# random Person
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

@classmethod def fromBirthYear(cls, name, birthYear): return cls(name, date.today().year - birthYear)
def display(self): print(self.name + "'s age is: " + str(self.age)) person = Person('Adam', 19) person.display() person1 = Person.fromBirthYear('John', 1985) person1.display()

输出

Adam's age is: 19
John's age is: 31

这里,我们有两个类实例创建器,一个构造函数和一个 fromBirthYear 方法。

构造函数接受普通参数 nameage。而 fromBirthYear 接受 classnamebirthYear,通过从当前年份中减去出生年份来计算当前年龄并返回类实例。

fromBirthYear 方法将 Person 类(而不是 Person 对象)作为第一个参数 cls,并通过调用 cls(name, date.today().year - birthYear) 返回构造函数,这等效于 Person(name, date.today().year - birthYear)

在该方法之前,我们看到 @classmethod。这称为将 fromBirthYear 转换为类方法(如 classmethod())的装饰器。


2. 继承中正确的实例创建

每当您从实现工厂方法作为类方法的类派生时,它都会确保派生类的正确实例创建。

您可以为上述示例创建一个静态方法,但它创建的对象将始终被硬编码为基类。

但是,当您使用类方法时,它会创建派生类的正确实例。

示例 3:类方法如何用于继承?

from datetime import date

# random Person
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @staticmethod
    def fromFathersAge(name, fatherAge, fatherPersonAgeDiff):
        return Person(name, date.today().year - fatherAge + fatherPersonAgeDiff)

@classmethod def fromBirthYear(cls, name, birthYear): return cls(name, date.today().year - birthYear)
def display(self): print(self.name + "'s age is: " + str(self.age)) class Man(Person): sex = 'Male' man = Man.fromBirthYear('John', 1985) print(isinstance(man, Man)) man1 = Man.fromFathersAge('John', 1965, 20) print(isinstance(man1, Man))

输出

True
False

在这里,使用静态方法创建类实例要求我们在创建时硬编码实例类型。

这在将 Person 继承到 Man 时显然会导致问题。

fromFathersAge 方法不返回 Man 对象,而是其基类 Person 的对象。

这违反了面向对象编程范式。使用类方法(如 fromBirthYear)可以确保代码的面向对象性,因为它将第一个参数作为类本身并调用其工厂方法。


另请阅读

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战