Python 当我可以在没有注释的情况下调用中的构造函数时,为什么要使用@classmethod?

Python 当我可以在没有注释的情况下调用中的构造函数时,为什么要使用@classmethod?,python,class-method,Python,Class Method,我研究了@classmethods的优点,发现我们可以从任何方法直接调用构造函数,既然如此,为什么我们需要一个类方法呢。是否有一些我错过的优势 为什么这样编码,有什么好处? 而不是这个代码:- 因为如果从Person派生,fromBirthYear将始终返回Person对象,而不是派生类 class Person: def __init__(self, name, age): self.name = name self.age = age def

我研究了@classmethods的优点,发现我们可以从任何方法直接调用构造函数,既然如此,为什么我们需要一个类方法呢。是否有一些我错过的优势

为什么这样编码,有什么好处? 而不是这个代码:-
因为如果从Person派生,fromBirthYear将始终返回Person对象,而不是派生类

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

    def fromBirthYear(name, year):
        return Person(name, year)


class Fred(Person):
    pass
print(Fred.fromBirthYear('bob', 2019))
输出:

<__main__.Person object at 0x6ffffcd7c88>

您可能希望
Fred.fromBirthYear
返回Fred对象

最终,这种语言会让你做很多不该做的事情。

from datetime import date
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def fromBirthYear(name, year):
        return Person(name, date.today().year - year)

    def __repr__(self):
        return f"Person('{self.name}', {self.age})"
只要您不通过
Person
的实例访问
fromBirthYear
,您的代码就可以找到:

>>> Person("bob", 2010)
Person('bob', 10)
但是,从
Person
的实例调用它不会:

>>> Person("bob", 2010).fromBirthYear("bob again", 10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: fromBirthYear() takes 2 positional arguments but 3 were given

最后,类方法的行为有点像静态方法,无论是从类还是从类的实例调用,都在接收的参数中保持一致。但是,与实例方法一样,它确实接收一个隐式参数:类本身,而不是类的实例。这里的好处是类方法返回的实例可以在运行时确定。假设您有一个子类
Person

from datetime import date
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    def __repr__(self):
        return f"Person('{self.name}', {self.age})"

class DifferentPerson(Person):
    pass
这两个类都可以用于从birthyear调用
,但返回值现在取决于调用它的类

>>> type(Person.fromBirthYear("bob", 2010))
<class '__main__.Person'>
>>> type(DifferentPerson.fromBirthYear("other bog", 2010))
<class '__main__.DifferentPerson'>
>类型(Person.fromBirthYear(“bob”,2010))
>>>类型(与出生年份(“其他沼泽地”,2010年)不同的人)

常规方法必须将
self
作为第一个参数。这是在python中创建替代构造函数的最常见方法。主要的好处是您可以使用类名调用方法,因为第二个代码不起作用。“试试看。”马克托洛宁说,这是一种工作;通过类(而不是类的实例)访问函数会生成函数本身,而不是方法。无论是从类还是从实例访问,正确的静态方法都会生成底层函数。
from datetime import date
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @staticmethod
    def fromBirthYear(name, year):
        return Person(name, date.today().year - year)

    def __repr__(self):
        return f"Person('{self.name}', {self.age})"


>>> Person.fromBirthYear("bob", 2010)
Person('bob', 10)
>>> Person.fromBirthYear("bob", 2010).fromBirthYear("bob again", 2015)
Person('bob again', 5)
from datetime import date
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def fromBirthYear(cls, name, year):
        return cls(name, date.today().year - year)

    def __repr__(self):
        return f"Person('{self.name}', {self.age})"

class DifferentPerson(Person):
    pass
>>> type(Person.fromBirthYear("bob", 2010))
<class '__main__.Person'>
>>> type(DifferentPerson.fromBirthYear("other bog", 2010))
<class '__main__.DifferentPerson'>