用@staticmethod修饰的方法和用@classmethod修饰的方法有什么区别?
当前回答
staticmethod无法访问继承层次结构中对象、类或父类的属性。它可以直接在类中调用(无需创建对象)。
classmethod无法访问对象的属性。但是,它可以访问继承层次结构中的类和父类的属性。它可以直接在类中调用(无需创建对象)。如果在对象处调用,则它与不访问self的普通方法相同<属性>并访问self__第__类<属性>。
假设我们有一个b=2的类,我们将创建一个对象,并将其重新设置为b=4。Staticmethod无法访问以前的任何内容。Classmethod只能通过cls.b访问.b==2。正常方法可以通过self访问:.b==4和.b==2__第__.b类。
我们可以遵循KISS风格(保持简单,愚蠢):不要使用静态方法和类方法,不要在没有实例化它们的情况下使用类,只访问对象的属性self.attribute。有些语言是这样实现OOP的,我认为这不是坏主意
其他回答
@classmethod:可用于创建对该类创建的所有实例的共享全局访问。。。。。比如由多个用户更新记录。。。。我特别发现它在创建单件时也很有用。:)
@静态方法:与关联的类或实例无关。。。但为了可读性,可以使用静态方法
我开始用C++学习编程语言,然后是Java,然后是Python,所以这个问题也困扰了我,直到我理解了每种语言的简单用法。
类方法:Python不像Java和C++那样没有构造函数重载。为了实现这一点,可以使用classmethod。以下示例将对此进行解释
让我们考虑一个Person类,它接受两个参数first_name和last_name,并创建Person的实例。
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
现在,如果您需要仅使用一个名称(仅使用first_name)创建一个类,那么在Python中不能这样做。
当您尝试创建对象(实例)时,这将给您一个错误。
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
def __init__(self, first_name):
self.first_name = first_name
然而,您可以使用@classmethod实现以下相同的功能
class Person(object):
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@classmethod
def get_person(cls, first_name):
return cls(first_name, "")
静态方法:这相当简单,它不绑定到实例或类,您可以使用类名简单地调用它。
所以,在上面的示例中,假设您需要验证first_name不应超过20个字符,您可以简单地这样做。
@staticmethod
def validate_name(name):
return len(name) <= 20
您可以使用类名调用
Person.validate_name("Gaurang Shah")
太长,读不下去了
静态方法本质上是绑定到类(及其实例)的函数
类方法本质上是一种可继承的静态方法。
有关详细信息,请参阅其他人的优秀答案。
只有第一个参数不同:
normal方法:当前对象作为(附加)第一个参数自动传递classmethod:当前对象的类自动作为(附加的)第一个参数传递staticmethod:不会自动传递额外的参数。传递给函数的就是得到的。
更详细地说。。。
正常方法
“标准”方法,如在所有面向对象的语言中。当调用对象的方法时,会自动为其提供一个额外的参数self作为其第一个参数。即,方法
def f(self, x, y)
必须使用2个参数调用。self是自动传递的,它是对象本身。类似于这个神奇地出现在例如java/c++中,只有在python中才显式显示。
实际上,第一个参数不必称为self,但它是标准的约定,所以请保留它
类方法
装饰方法时
@classmethod
def f(cls, x, y)
自动提供的参数不是self,而是self的类。
静态法
装饰方法时
@staticmethod
def f(x, y)
该方法根本没有给出任何自动参数。它只提供调用它的参数。
用法
classmethod主要用于替代构造函数。staticmethod不使用对象的状态,甚至不使用类本身的结构。它可以是类外部的函数。它只放在类中,用于对具有类似功能的函数进行分组(例如,像Java的Math类静态方法)
class Point
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def frompolar(cls, radius, angle):
"""The `cls` argument is the `Point` class itself"""
return cls(radius * cos(angle), radius * sin(angle))
@staticmethod
def angle(x, y):
"""this could be outside the class, but we put it here
just because we think it is logically related to the class."""
return atan(y, x)
p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)
angle = Point.angle(3, 2)
@staticmethod只是禁用默认函数作为方法描述符。classmethod将函数包装在可调用的容器中,该容器将引用作为第一个参数传递给所属类:
>>> class C(object):
... pass
...
>>> def f():
... pass
...
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>
事实上,classmethod有运行时开销,但可以访问所属的类。或者,我建议使用元类并将类方法放在元类上:
>>> class CMeta(type):
... def foo(cls):
... print cls
...
>>> class C(object):
... __metaclass__ = CMeta
...
>>> C.foo()
<class '__main__.C'>
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录