@classmethod 和 @staticmethod 对初学者的意义? [英] Meaning of @classmethod and @staticmethod for beginner?

查看:30
本文介绍了@classmethod 和 @staticmethod 对初学者的意义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能给我解释一下python中@classmethod@staticmethod的含义?我需要知道区别和含义.

Could someone explain to me the meaning of @classmethod and @staticmethod in python? I need to know the difference and the meaning.

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

As far as I understand, @classmethod tells a class that it's a method which should be inherited into subclasses, or... something. However, what's the point of that? Why not just define the class method without adding @classmethod or @staticmethod or any @ definitions?

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

tl;dr: when should I use them, why should I use them, and how should I use them?

推荐答案

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

Though classmethod and staticmethod are quite similar, there's a slight difference in usage for both entities: classmethod must have a reference to a class object as the first parameter, whereas staticmethod can have no parameters at all.

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')

说明

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

Explanation

Let's assume an example of a class, dealing with date information (this will be our boilerplate):

class Date(object):

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

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

This class obviously could be used to store information about certain dates (without timezone information; let's assume all dates are presented in UTC).

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

Here we have __init__, a typical initializer of Python class instances, which receives arguments as a typical instancemethod, having the first non-optional argument (self) that holds a reference to a newly created instance.

类方法

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

We have some tasks that can be nicely done using classmethods.

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

Let's assume that we want to create a lot of Date class instances having date information coming from an outer source encoded as a string with format 'dd-mm-yyyy'. Suppose we have to do this in different places in the source code of our project.

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

So what we must do here is:

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

这看起来像:

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

为此,C++ 可以通过重载来实现这样的特性,但是 Python 缺少这种重载.相反,我们可以使用 classmethod.让我们创建另一个构造函数".

For this purpose, C++ can implement such a feature with overloading, but Python lacks this overloading. Instead, we can use classmethod. Let's create another "constructor".

    @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')

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

Let's look more carefully at the above implementation, and review what advantages we have here:

  1. 我们在一处实现了日期字符串解析,现在可以重复使用了.
  2. 封装在这里工作正常(如果您认为可以在其他地方将字符串解析作为单个函数来实现,则此解决方案更适合 OOP 范式).
  3. cls 是一个保存类本身的对象,而不是类的实例.这很酷,因为如果我们继承我们的 Date 类,所有的孩子都会同时定义 from_string .
  1. We've implemented date string parsing in one place and it's reusable now.
  2. Encapsulation works fine here (if you think that you could implement string parsing as a single function elsewhere, this solution fits the OOP paradigm far better).
  3. cls is an object that holds the class itself, not an instance of the class. It's pretty cool because if we inherit our Date class, all children will have from_string defined also.

静态方法

staticmethod 怎么样?它与 classmethod 非常相似,但不接受任何强制参数(就像类方法或实例方法那样).

What about staticmethod? It's pretty similar to classmethod but doesn't take any obligatory parameters (like a class method or instance method does).

让我们看看下一个用例.

Let's look at the next use case.

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

We have a date string that we want to validate somehow. This task is also logically bound to the Date class we've used so far, but doesn't require instantiation of it.

这里是 staticmethod 有用的地方.我们来看下一段代码:

Here is where staticmethod can be useful. Let's look at the next piece of code:

    @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 则可以.

So, as we can see from usage of staticmethod, we don't have any access to what the class is---it's basically just a function, called syntactically like a method, but without access to the object and its internals (fields and another methods), while classmethod does.

这篇关于@classmethod 和 @staticmethod 对初学者的意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆