oop - python @classmethod和@staticmethod初学者?

  显示原文与译文双语对照的内容

我知道这个主题上有很多资源,但因为英语不是我的母语,这是我第一次使用 python,我需要一些帮助: 有人能解释 @classmethod@staticmethod的含义? 我不仅要知道区别,还要知道意义。 我已经阅读过一些文档,但我完全看不懂它。 如果有人能给我一个清晰的定义和一个例子,那将是很棒的- 我从示例中学到最好的。

据我所知,@classmethod 告诉类它是应该继承到子类中的方法,或者。 但是,这意味着什么? 为什么不直接定义类方法而不添加 @classmethod 或者 @staticmethod 或者任何 @ 定义?

tl;博士: 我应该使用它们时,为什么我使用它们,我应该如何使用它们呢?

我对 C++ 非常高级,所以使用更高级的编程概念不应该是一个问题。 如果可能的话,请给我一个相应的C++ 示例。

时间:

Rostyslav的答案非常合适。 我想我可以强调一下,你应该选择 @classmethod 胜过 @staticmethod

在上面的示例中,Rostyslav使用 @classmethodfrom_string 作为一个工厂来创建来自其他不可接受的参数的Date 对象。 @staticmethod 也可以这样做,如下代码所示:


class Date:
 def __init__(self, month, day, year):
 self.month = month
 self.day = day
 self.year = year


 def display(self):
 return"{0}-{1}-{2}".format(self.month, self.day, self.year)


 @staticmethod
 def millenium(month, day):
 return Date(month, day, 2000)

new_year = Date(1, 1, 2013) # Creates a new Date object
millenium_new_year = Date.millenium(1, 1) # also creates a Date object. 

# Proof:
new_year.display() #"1-1-2013"
millenium_new_year.display() #"1-1-2000"

isinstance(new_year, Date) # True
isinstance(millenium_new_year, Date) # True

因此 new_yearmillenium_new_year 都是 Date 类的实例。

但是如果你仔细观察,工厂的进程是hard-coded创建 Date 对象无论什么东西。 这意味着即使 Date 类是子类,子类仍然会创建普通的Date 对象( 没有子类的任何属性) 。 请参见下面的示例:


class DateTime(Date):
 def display(self):
 return"{0}-{1}-{2} - 00:00:00PM".format(self.month, self.day, self.year)


datetime1 = DateTime(10, 10, 1990)
datetime2 = DateTime.millenium(10, 10)

isinstance(datetime1, DateTime) # True
isinstance(datetime2, DateTime) # False

datetime1.display() # returns"10-10-1990 - 00:00:00PM"
datetime2.display() # returns"10-10-2000" because it's not a DateTime object but a Date object. Check the implementation of the millenium method on the Date class

datetime2 不是 DateTime的实例? WTF那是因为使用了 @staticmethod decorator 。

在大多数情况下,这是不需要的。 如果你想要的是一个知道调用它的类的工厂方法,那么 @classmethod 就是你需要的。

重写 Date.millenium ( 这是上述代码的唯一部分)


@classmethod
def millenium(cls, month, day):
 return cls(month, day, 2000)

确保 class 不是 hard-coded,而是学习。 cls 可以是任何子类。 结果 object 将是 cls的一个实例。 我们来测试一下。


datetime1 = DateTime(10, 10, 1990)
datetime2 = DateTime.millenium(10, 10)

isinstance(datetime1, DateTime) # True
isinstance(datetime2, DateTime) # True


datetime1.display() #"10-10-1990 - 00:00:00PM"
datetime2.display() #"10-10-2000 - 00:00:00PM"

原因是,就像你现在所知,@classmethod 被使用而不是 @staticmethod

@classmethod 表示:当调用这个方法时,我们将类作为第一个参数传递,而不是这个类的实例。 这意味着你可以在该方法中使用类及其属性,而不是使用特定的实例。

@staticmethod 表示:当调用这里方法时,我们不会将类的实例传递给它( 我们通常用方法来做) 。 这意味着你可以在类中放置一个函数,但不能访问该类的实例( 当你的方法不使用实例时,这很有用) 。

@staticmethod 函数只不过是一个在类内定义的函数。 它可以在不先实例化类的情况下调用。 它的定义是通过继承不可变的。

  • python 不需要为对象实例化 bound-method 。
  • 它简化了代码的可读性: 查看 @ staticmethod,我们知道该方法不依赖于对象本身的状态;

@classmethod 函数也可以调用而不实例化该类,但它的定义遵循继承,而不是父类,通过继承可以被子类覆盖。 这是因为 @classmethod 函数的第一个参数必须总是 cls ( 类) 。

  • 用于为类创建实例的工厂方法,例如某种 pre-processing 。
  • 静态方法调用静态方法: 如果在多个静态方法中拆分静态方法,则不应该使用类名,而是使用类方法

这里的是这里主题的好链接。

...