本文翻译自:Meaning of @classmethod and @staticmethod for beginner? [duplicate]

This question already has an answer here: 这个问题在这里已有答案:

  • What is the difference between @staticmethod and @classmethod? @staticmethod和@classmethod有什么区别? 23 answers 23个答案

Could someone explain to me the meaning of @classmethod and @staticmethod in python? 有人可以向我解释@classmethod@staticmethod在python中的含义吗? I need to know the difference and the meaning. 我需要知道差异和意义。

As far as I understand, @classmethod tells a class that it's a method which should be inherited into subclasses, or... something. 据我所知, @classmethod告诉一个类,它是一个应该继承到子类的方法,或者......某种东西。 However, what's the point of that? 但是,重点是什么? Why not just define the class method without adding @classmethod or @staticmethod or any @ definitions? 为什么不在不添加@classmethod@staticmethod或任何@ definitions的情况下定义类方法?

tl;dr: when should I use them, why should I use them, and how should I use them? tl; dr:我应该何时使用它们, 为什么要使用它们,我应该如何使用它们?

I'm pretty advanced with C++, so using more advanced programming concepts shouldn't be a problem. 我在C ++方面非常先进,所以使用更高级的编程概念应该不是问题。 Feel free giving me a corresponding C++ example if possible. 如果可能的话,请随意给我一个相应的C ++示例。


#1楼

参考:https://stackoom.com/question/p6Nr/classmethod和-staticmethod对初学者的意义-重复


#2楼

@classmethod means: when this method is called, we pass the class as the first argument instead of the instance of that class (as we normally do with methods). @classmethod意味着:当调用此方法时,我们将类作为第一个参数而不是该类的实例传递(正如我们通常使用的方法)。 This means you can use the class and its properties inside that method rather than a particular instance. 这意味着您可以在该方法中使用类及其属性,而不是特定实例。

@staticmethod means: when this method is called, we don't pass an instance of the class to it (as we normally do with methods). @staticmethod意味着:当调用此方法时,我们不会将类的实例传递给它(正如我们通常使用的方法)。 This means you can put a function inside a class but you can't access the instance of that class (this is useful when your method does not use the instance). 这意味着您可以将一个函数放在一个类中,但是您无法访问该类的实例(当您的方法不使用该实例时,这很有用)。


#3楼

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. 尽管classmethodstaticmethod非常相似,但两个实体的使用情况略有不同: classmethod必须引用类对象作为第一个参数,而staticmethod根本没有参数。

Example

class Date(object):def __init__(self, day=0, month=0, year=0):self.day = dayself.month = monthself.year = year@classmethoddef from_string(cls, date_as_string):day, month, year = map(int, date_as_string.split('-'))date1 = cls(day, month, year)return date1@staticmethoddef is_date_valid(date_as_string):day, month, year = map(int, date_as_string.split('-'))return day <= 31 and month <= 12 and year <= 3999date2 = 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 = dayself.month = monthself.year = year

This class obviously could be used to store information about certain dates (without timezone information; let's assume all dates are presented in UTC). 这个类显然可以用来存储关于某些日期的信息(没有时区信息;我们假设所有日期都以UTC表示)。

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

Class Method 类方法

We have some tasks that can be nicely done using classmethod s. 我们有一些使用classmethod可以很好地完成的任务。

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'. 假设我们想要创建许多Date类实例,其日期信息来自外部源,编码为格式为'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. Parse a string to receive day, month and year as three integer variables or a 3-item tuple consisting of that variable. 解析字符串以接收日,月和年作为三个整数变量或由该变量组成的3项元组。
  2. Instantiate Date by passing those values to the initialization call. 通过将这些值传递给初始化调用来实例化Date

This will look like: 这看起来像:

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

For this purpose, C++ can implement such a feature with overloading, but Python lacks this overloading. 为此,C ++可以通过重载实现这样的功能,但是Python缺少这种重载。 Instead, we can use classmethod . 相反,我们可以使用classmethod Let's create another " constructor ". 让我们创建另一个“ 构造函数 ”。

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

Let's look more carefully at the above implementation, and review what advantages we have here: 让我们更仔细地看一下上面的实现,并回顾一下我们在这里有什么优势:

  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). 封装在这里工作正常(如果你认为你可以在其他地方实现字符串解析作为单个函数,这个解决方案更适合OOP范例)。
  3. cls is an object that holds the class itself , not an instance of the class. cls是一个保存类本身的对象,而不是的实例。 It's pretty cool because if we inherit our Date class, all children will have from_string defined also. 这很酷,因为如果我们继承Date类,所有子from_string定义from_string

Static method 静态方法

What about staticmethod ? staticmethod怎么样? It's pretty similar to classmethod but doesn't take any obligatory parameters (like a class method or instance method does). 它与classmethod非常相似,但不采用任何强制参数(如类方法或实例方法)。

Let's look at the next use case. 我们来看看下一个用例。

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. 此任务在逻辑上也绑定到我们目前使用的Date类,但不需要实例化它。

Here is where staticmethod can be useful. 这是staticmethod方法可能有用的地方。 Let's look at the next piece of code: 让我们看看下一段代码:

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

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. 因此,正如我们从staticmethod使用中看到的那样,我们无法访问类的内容 - 它基本上只是一个函数,在语法上称为方法,但无法访问对象及其内部(字段和另一种方法),而classmethod。


#4楼

Rostyslav Dzinko's answer is very appropriate. Rostyslav Dzinko的回答非常合适。 I thought I could highlight one other reason you should choose @classmethod over @staticmethod when you are creating an additional constructor. 我想我可以强调另一个原因,当你创建一个额外的构造函数时,你应该选择@classmethod不是@staticmethod

In the example above, Rostyslav used the @classmethod from_string as a Factory to create Date objects from otherwise unacceptable parameters. 在上面的示例中,Rostyslav使用@classmethod from_string作为Factory从其他不可接受的参数创建Date对象。 The same can be done with @staticmethod as is shown in the code below: 使用@staticmethod可以完成同样的操作,如下面的代码所示:

class Date:def __init__(self, month, day, year):self.month = monthself.day   = dayself.year  = yeardef display(self):return "{0}-{1}-{2}".format(self.month, self.day, self.year)@staticmethoddef 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

Thus both new_year and millenium_new_year are instances of the Date class. 因此,不论new_yearmillenium_new_year是实例Date类。

But, if you observe closely, the Factory process is hard-coded to create Date objects no matter what. 但是,如果仔细观察,工厂流程将被硬编码以创建Date对象,无论如何。 What this means is that even if the Date class is subclassed, the subclasses will still create plain Date objects (without any properties of the subclass). 这意味着即使Date类是子类,子类仍将创建普通的Date对象(没有子类的任何属性)。 See that in the example below: 请参阅以下示例中的内容:

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) # Falsedatetime1.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 for more details.

datetime2 is not an instance of DateTime ? datetime2不是DateTime的实例? WTF? WTF? Well, that's because of the @staticmethod decorator used. 嗯,这是因为使用了@staticmethod装饰器。

In most cases, this is undesired. 在大多数情况下,这是不希望的。 If what you want is a Factory method that is aware of the class that called it, then @classmethod is what you need. 如果你想要的是一个知道调用它的类的Factory方法,那么@classmethod就是你需要的。

Rewriting Date.millenium as (that's the only part of the above code that changes): Date.millenium重写为(这是上述代码中唯一改变的部分):

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

ensures that the class is not hard-coded but rather learnt. 确保class不是硬编码而是学习。 cls can be any subclass. cls可以是任何子类。 The resulting object will rightly be an instance of cls . 生成的object将正确地成为cls的实例。
Let's test that out: 让我们测试出来:

datetime1 = DateTime(10, 10, 1990)
datetime2 = DateTime.millenium(10, 10)isinstance(datetime1, DateTime) # True
isinstance(datetime2, DateTime) # Truedatetime1.display() # "10-10-1990 - 00:00:00PM"
datetime2.display() # "10-10-2000 - 00:00:00PM"

The reason is, as you know by now, that @classmethod was used instead of @staticmethod 原因是,正如您现在@classmethod ,使用@staticmethod而不是@staticmethod


#5楼

When to use each 何时使用每个

@staticmethod function is nothing more than a function defined inside a class. @staticmethod函数只不过是在类中定义的函数。 It is callable without instantiating the class first. 它可以在不首先实例化类的情况下调用。 It's definition is immutable via inheritance. 它的定义是通过继承不可变的。

  • Python does not have to instantiate a bound-method for object. Python不必实例化对象的绑定方法 。
  • It eases the readability of the code: seeing @staticmethod , we know that the method does not depend on the state of object itself; 它简化了代码的可读性:看到@staticmethod ,我们知道该方法不依赖于对象本身的状态;

@classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance, can be overridden by subclass. @classmethod函数也可以在不实例化类的情况下调用,但是它的定义遵循Sub类,而不是Parent类,通过继承,可以被子类覆盖。 That's because the first argument for @classmethod function must always be cls (class) . 那是因为@classmethod函数的第一个参数必须始终是cls (class)

  • Factory methods , that are used to create an instance for a class using for example some sort of pre-processing. 工厂方法 ,用于为类创建实例,例如使用某种预处理。
  • Static methods calling static methods : if you split a static methods in several static methods, you shouldn't hard-code the class name but use class methods 调用静态方法的静态方法 :如果在多个静态方法中拆分静态方法,则不应对类名进行硬编码,而应使用类方法

here is good link to this topic. 这里是这个主题的好链接。


#6楼

A little compilation 一点汇编

@staticmethod A way to write a method inside a class without reference to the object it is being called on. @staticmethod一种在类中编写方法而不引用它所调用的对象的方法。 So no need to pass implicit argument like self or cls. 所以不需要传递像self或cls这样的隐式参数。 It is written exactly the same how written outside the class, but it is not of no use in python because if you need to encapsulate a method inside a class since this method needs to be the part of that class @staticmethod is comes handy in that case. 它的写法与在类外写的完全相同,但它在python中没有用,因为如果你需要在类中封装一个方法,因为这个方法需要成为该类的一部分@staticmethod就派上用了案件。

@classmethod It is important when you want to write a factory method and by this custom attribute(s) can be attached in a class. @classmethod当你想编写一个工厂方法时,这很重要,并且这个自定义属性可以附加在一个类中。 This attribute(s) can be overridden in the inherited class. 可以在继承的类中重写此属性。

A comparison between these two methods can be as below 这两种方法之间的比较如下

@classmethod和@staticmethod对初学者的意义? [重复]相关推荐

  1. [转载] python classmethod存在的意义_@classmethod和@staticmethod对初学者的意义?

    参考链接: Python classmethod() 尽管classmethod和staticmethod非常相似,但这两个实体的用法略有不同:classmethod必须将对类对象的引用作为第一个参数 ...

  2. [转载] python staticmethod有什么意义_Python 中的 classmethod 和 staticmethod 有什么具体用途

    参考链接: Python staticmethod() >>> type(a1) example 2: class a(object): @classmethod def cm(cl ...

  3. python知识:@classmethod和@staticmethod的异同

    1 说明 @staticmethod的意思就是将后面的函数转化成静态函数. 大多数情况,@classmethod和@staticmethod效果一样.但是那不是正题,正式作用是类工厂,如果有类继承关系 ...

  4. python classmethod知识_python基础知识讲解——@classmethod和@staticmethod的作用

    python基础知识讲解--@classmethod和@staticmethod的作用 在类的成员函数中,可以添加@classmethod和@staticmethod修饰符,这两者有一定的差异,简单来 ...

  5. python @classmethod 和 @staticmethod区别,以及类中方法参数cls和self的区别

    一.@classmethod 和 @staticmethod 1.staticmethod 作用:让类中的方法变成一个普通函数(普通函数没有绑定在任何一个特定的类或者实例上.所以与不需要对象实例化就可 ...

  6. python的@classmethod和@staticmethod

    本文是对StackOverflow上的一篇高赞回答的不完全翻译,原文链接:meaning-of-classmethod-and-staticmethod-for-beginner Python面向对象 ...

  7. python中classmethod与staticmethod的差异及应用

    类中三种函数的应用 #!/usr/bin/env python # -*- coding: utf-8 -*-class TClassStatic(object):def __init__(self, ...

  8. python中各种@property、@xxx.setter、@classmethod、@staticmethod 都是些啥啊?

    时不时看到有友友对一些 Python 方法的定义感到疑惑:为啥要在方法上面要各种 @ ? 类似这样: 这是你最常见的几个玩意了吧,它们都是啥意思,以及怎么去定义使用呢? 那么,接下来我就尽量通熟易懂的 ...

  9. classmethod和staticmethod

    两个装饰器 classmethod : 被装饰的方法会成为一个静态方法 classmethod 什么时候用? 定义了一个方法,默认传self,但是这个self没有被用到 并且你在这个方法里用到了当前的 ...

最新文章

  1. OpenCV——图像的平移旋转
  2. sublime_REPL使用及安装教程(解决Sublime无交互问题)
  3. (仿头条APP项目)7.首页标签页完善和微头条页面设计实现
  4. docker svn
  5. android多语言编码格式,在Android中使用国家/地区代码以编程方式更改语言
  6. .netcore下的微服务、容器、运维、自动化发布
  7. asp用于取代什么技术_苹果Mini LED晶粒四季度量产,用于新iPad Pro,三安光电或成赢家...
  8. 【kafka】Kafka leader -1
  9. 记录一次奇葩的sleep(15)引起的Too many connections
  10. python函数abs()
  11. Bootstrap下拉菜单相关
  12. 弗尤博客(十)之聊天室
  13. 在一个公司,谁有业绩,谁就有说话权
  14. linux修改shell前缀,Linux shell控制台改变显示前缀
  15. 万字拆解欧莱雅:百年美妆帝国的数字化远征
  16. 宝付国际一文读懂:跨境电商的外汇风险敞口(一)
  17. 桌面上计算机程序包能删吗,不小心卸载了windows驱动程序包(电脑上别乱清理了)...
  18. 证明N={1,2,...,n,...}有最大元 黄小宁
  19. 【苹果家庭推送iMessage】软件安装应用程序访问HealthKit HomeKit
  20. git 提交时报错 error: failed to push some refs to ‘https://github.com/xxx/demo.git 解决方法

热门文章

  1. Android:面试官死亡问答,如何优化一个网络请求?大牛多个网络优化方案帮你解决!
  2. 从前到后的CAN总线(一)
  3. ipad php mysql_如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1
  4. Flutter之Dart入门
  5. winform 监听http_Winform HttpListener监听有关问题
  6. uniapp定义全局变量方法
  7. codeforces316E3
  8. webpack 安装卸载
  9. SpringMVC源码解析
  10. [P1363] 幻想迷宫