@classmethod 和 @staticmethod 对初学者的意义?

发布于 2022-02-17 09:37:43

有人可以向我解释python中@classmethod和的含义吗?@staticmethod我需要知道区别和含义。

据我了解,@classmethod告诉一个类它是一个应该被继承到子类中的方法,或者......什么。然而,这有什么意义呢?为什么不直接定义类方法而不添加@classmethodor@staticmethod或任何@定义?

tl;dr:我应该什么 时候使用它们,为什么要使用它们,我应该如何使用它们?

关注者
0
被浏览
56
1 个回答
  • 面试哥
    面试哥 2022-02-17
    为面试而生,有面试问题,就找面试哥。

    虽然classmethodstaticmethod非常相似,但两个实体的用法略有不同:classmethod必须将类对象的引用作为第一个参数,而staticmethod可以根本没有参数。

    例子

    class Date(object):
    
        def __init__(self, day=0, month=0, year=0):
            self.day = day
            self.month = month
            self.year = year
    
        @classmethod
        def from_string(cls, date_as_string):
            day, month, year = map(int, date_as_string.split('-'))
            date1 = cls(day, month, year)
            return date1
    
        @staticmethod
        def is_date_valid(date_as_string):
            day, month, year = map(int, date_as_string.split('-'))
            return day <= 31 and month <= 12 and year <= 3999
    
    date2 = Date.from_string('11-09-2012')
    is_date = Date.is_date_valid('11-09-2012')
    

    例子

    让我们假设一个类的例子,处理日期信息(这将是我们的样板):

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

    这个类显然可用于存储有关某些日期的信息(没有时区信息;假设所有日期都以 UTC 表示)。

    这里我们有__init__一个 Python 类实例的典型初始化器,它接收参数作为典型的instancemethod,具有第一个非可选参数 ( self),它包含对新创建实例的引用。

    类方法

    我们有一些任务可以使用classmethods 很好地完成。

    假设我们要创建许多Date类实例,这些实例的日期信息来自外部源,编码为格式为“dd-mm-yyyy”的字符串。假设我们必须在项目源代码的不同位置执行此操作。

    所以我们必须在这里做的是:

    1. 解析字符串以接收日、月和年作为三个整数变量或由该变量组成的 3 项元组。
    2. Date通过将这些值传递给初始化调用来实例化。

    这看起来像:

    day, month, year = map(int, string_date.split('-'))
    date1 = Date(day, month, year)
    

    为此,C++ 可以通过重载实现这样的功能,但 Python 缺少这种重载。相反,我们可以使用classmethod. 让我们创建另一个“构造函数”。

        @classmethod
        def from_string(cls, date_as_string):
            day, month, year = map(int, date_as_string.split('-'))
            date1 = cls(day, month, year)
            return date1
    
    date2 = Date.from_string('11-09-2012')
    

    让我们更仔细地看一下上面的实现,并回顾一下我们在这里有什么优势:

    1. 我们已经在一个地方实现了日期字符串解析,现在它可以重用了。
    2. 封装在这里工作得很好(如果您认为可以在其他地方将字符串解析实现为单个函数,则此解决方案更适合 OOP 范式)。
    3. cls是一个包含类本身的对象,而不是类的实例。这很酷,因为如果我们继承我们的Date类,所有的孩子也将被from_string定义。

    静态方法

    怎么样staticmethod?它非常类似于classmethod但不采用任何强制性参数(就像类方法或实例方法一样)。

    让我们看下一个用例。

    我们有一个想要以某种方式验证的日期字符串。此任务在逻辑上也绑定到Date我们目前使用的类,但不需要对其进行实例化。

    这是staticmethod有用的地方。让我们看下一段代码:

        @staticmethod
        def is_date_valid(date_as_string):
            day, month, year = map(int, date_as_string.split('-'))
            return day <= 31 and month <= 12 and year <= 3999
    
        # usage:
        is_date = Date.is_date_valid('11-09-2012')
    

    因此,正如我们从 的用法中看到的那样staticmethod,我们无法访问类是什么——它基本上只是一个函数,在语法上像方法一样被调用,但无法访问对象及其内部结构(字段和另一个方法),而 classmethod 可以。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看