classmethod()方法返回给定函数的类方法。
classmethod()方法的语法为:
classmethod(function)
classmethod()被认为是不符合Python规范的,所以在较新的Python版本中,可以使用@classmethod装饰器来定义类方法。
语法为:
@classmethod def func(cls, args...)
classmethod()方法采用一个参数:
function-需要转换为类方法的函数
classmethod()方法返回给定函数的类方法。
类方法是绑定到类而不是对象的方法。它不需要创建类示例,就像classmethod(静态方法)一样。
静态方法和类方法之间的区别是:
静态方法对类一无所知,只处理参数
类方法与类一起使用,因为其参数始终是类本身。
类方法可以由类及其对象调用。
Class.classmethod() Or even Class().classmethod()
但是无论如何,类方法始终附加到具有第一个参数的类,因为类本身为cls。
def classMethod(cls, args...)
class Person: age = 25 def printAge(cls): print('年龄是:', cls.age) # create printAge class method Person.printAge = classmethod(Person.printAge) Person.printAge()
运行该程序时,输出为:
年龄是: 25
在这里,我们有一个class Person,其成员变量age被指定为25。
我们还有一个函数printAge,它只接受一个参数cls,而不是我们通常使用的self。
cls接受类Person作为参数,而不是Person的对象/示例。
现在,我们将该方法Person.printAge作为参数传递给该函数classmethod。这会将方法转换为类方法,以便它接受第一个参数作为类(即Person)。
在最后一行中,调用时printAge没有像静态方法那样创建Person对象。这将打印类变量age。
工厂方法是那些针对不同用例返回类对象(如构造函数)的方法。
它类似于C ++中的函数重载。由于Python没有这样的功能,因此使用了类方法和静态方法。
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方法。
构造函数采用常规参数name和age。而fromBirthYear采用cls,name和birthYear,通过用当前年份减去当前年龄来计算当前年龄,并返回类示例。
fromBirthYear方法将Person类(不是Person对象)作为第一个参数cls,并通过调用返回构造函数cls(name, date.today().year - birthYear),这等效于Person(name, date.today().year - birthYear)
在该方法之前,我们看到了@classmethod。这称为装饰器,用于转换fromBirthYear为classmethod()的类方法。
每当将工厂方法实现为类方法来派生一个类时,它都可以确保正确创建派生类的示例。
您可以为上面的示例创建一个静态方法,但是它创建的对象将始终被硬编码为Base类。
但是,当您使用类方法时,它将创建派生类的正确示例。
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的对象。
这违反了OOP范式。使用类方法fromBirthYear可以确保代码的面向对象,因为它将第一个参数作为类本身并调用其工厂方法。