📜  Python classmethod()

📅  最后修改于: 2020-09-20 03:54:23             🧑  作者: Mango

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

classmethod()方法的语法为:

classmethod(function)

classmethod()被认为是非Python语言的,因此在较新的Python版本中,可以使用@classmethod装饰器进行classmethod定义。

语法为:

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

classmethod()参数

classmethod()方法采用一个参数:

  1. 函数需要转换为类方法的函数

从classmethod()返回值

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

什么是类方法?

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

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

  1. 静态方法对类一无所知,只处理参数
  2. 类方法与类一起使用,因为其参数始终是类本身。

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

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

但是无论如何,class方法总是以第一个参数作为类本身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)等效Person(name, date.today().year - birthYear)

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

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

每当将工厂方法实现为类方法来派生一个类时,它都会确保正确创建派生类的实例。

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

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

示例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

在这里,使用静态方法创建类实例需要我们在创建过程中对实例类型进行硬编码。

继承时,这显然会导致出现问题PersonMan

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

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