Python类方法:备用初始化器
示例
类方法提供了构建类实例的替代方法。为了说明,让我们看一个例子。
假设我们有一个相对简单的Person类:
class Person(object): def __init__(self, first_name, last_name, age): self.first_name= first_name self.last_name= last_name self.age= age self.full_name= first_name + " " + last_name def greet(self): print("Hello, my name is " +self.full_name+ ".")
有一种方法可以方便地构建此类的实例,该实例指定一个全名而不是分别使用名字和姓氏。一种实现方法是拥有last_name一个可选参数,并假设没有给出,我们在以下位置传递全名:
class Person(object): def __init__(self, first_name, age, last_name=None): if last_name is None: self.first_name,self.last_name= first_name.split(" ", 2) else: self.first_name= first_name self.last_name= last_name self.full_name=self.first_name+ " " + self.last_name self.age= age def greet(self): print("Hello, my name is " +self.full_name+ ".")
但是,这段代码有两个主要问题:
参数first_name和last_name现在具有误导性,因为您可以输入的全名first_name。同样,如果有更多情况和/或更多参数具有这种灵活性,则if/elif/else分支会变得很烦人。
不是很重要,但仍然值得指出:如果last_name是None,但first_name没有通过空格分裂为两个或更多的东西呢?我们还有另一层输入验证和/或异常处理...
输入类方法。我们将创建一个名为的单独的初始化器,而不是使用单个初始化器from_full_name,并使用(内置)classmethod装饰器对其进行装饰。
class Person(object): def __init__(self, first_name, last_name, age): self.first_name= first_name self.last_name= last_name self.age= age self.full_name= first_name + " " + last_name @classmethod def from_full_name(cls, name, age): if " " not in name: raise ValueError first_name, last_name = name.split(" ", 2) return cls(first_name, last_name, age) def greet(self): print("Hello, my name is " +self.full_name+ ".")
注意,cls而不是self作为第一个参数from_full_name。类方法应用于整个类,而不是给定类的实例(self通常表示)。所以,如果cls是我们的Person班,然后从返回的值from_full_name类的方法是Person(first_name,last_name,age),使用它Person的__init__创建的实例Person类。特别是,如果我们做一个子类Employee的Person,然后from_full_name将在工作Employee类为好。
为了表明它能按预期工作,让我们Person以多种方式创建实例,而无需分支__init__:
In [2]: bob = Person("Bob", "Bobberson", 42) In [3]: alice = Person.from_full_name("Alice Henderson", 31) In [4]: bob.greet() Hello, my name is Bob Bobberson. In [5]: alice.greet() Hello, my name is Alice Henderson.
其他参考:
初学者使用Python@classmethod和@staticmethod吗?
https://docs.python.org/2/library/functions.html#classmethod
https://docs.python.org/3.5/library/functions.html#classmethod