聊天中已经讨论了一个问题(该问题本身与该问题无关),这表明我可能不知道Python。
在我看来,尽管术语在不同语言之间是不同的,但我们通常可以将功能归类为:
- [免费]功能
- 静态方法/静态成员函数
- 非静态方法/非静态成员函数
显然,在Python中,还有另一种不适用于上述类别的函数,一种是方法,但“不知道其类”。
在Python中,什么是“类方法”和“实例方法”?
聊天中已经讨论了一个问题(该问题本身与该问题无关),这表明我可能不知道Python。
在我看来,尽管术语在不同语言之间是不同的,但我们通常可以将功能归类为:
显然,在Python中,还有另一种不适用于上述类别的函数,一种是方法,但“不知道其类”。
在Python中,什么是“类方法”和“实例方法”?
Answers:
甲类方法是一个属于类作为一个整体。它不需要实例。相反,该类将自动作为第一个参数发送。@classmethod
装饰器声明了一个类方法。
例如:
class Foo(object):
@classmethod
def hello(cls):
print("hello from %s" % cls.__name__)
Foo.hello()
-> "Hello from Foo"
Foo().hello()
-> "Hello from Foo"
另一方面,实例方法 需要一个实例才能调用它,并且不需要装饰器。到目前为止,这是最常见的方法类型。
class Foo(object):
def hello(self):
print("hello from %s" % self.__class__.__name__)
Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'self'
(注意:以上是针对python3的;对于python2,您会得到略有不同的错误)
甲静态方法是类似于类的方法,但不会得到类对象作为自动参数。它是通过使用@staticmethod
装饰器创建的。
class Foo(object):
@staticmethod
def hello(cls):
print("hello from %s" % cls.__name__)
Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'cls'
以下是相关python3文档的链接:
该数据模型文件有这样说的类方法和静态方法的区别:
静态方法对象静态方法对象提供了一种克服功能对象向上述方法对象的转换的方法。静态方法对象是任何其他对象(通常是用户定义的方法对象)的包装。从类或类实例中检索静态方法对象时,实际返回的对象是包装的对象,无需进行任何进一步的转换。静态方法对象本身不是可调用的,尽管它们通常包装的对象是可调用的。静态方法对象由内置的staticmethod()构造函数创建。
类方法对象 类方法对象与静态方法对象一样,是另一个对象的包装,它更改了从类和类实例检索该对象的方式。上面在“用户定义的方法”下描述了此类检索时类方法对象的行为。类方法对象是由内置的classmethod()构造函数创建的。
"^ def("
,然后计算了的所有实例@staticmethod
。非常不科学,但可能在球场附近。
在Python中,什么是“类方法”和“实例方法”?
“实例方法”使用实例中包含的信息来计算要返回的值(或要执行的副作用)。这些很常见。
“类方法”使用有关类的信息(而不是该类的实例)来影响其功能(它们通常用于创建新实例作为替代构造函数,因此并不常见)。
“静态方法”不使用有关类或实例的任何信息来计算其功能。为了方便起见,通常只在课堂上讲。(因此,它们也不是很常见。)
记住数学课,“ y是x的函数f(x)
吗?” 让我们在代码中应用它:
y = function(x)
以上所隐含的是,由于x
可能会更改,所以y
更改时可能会x
更改。这就是说“ y
是”的功能时的x
意思。
将什么y
是时候z
是1
?2
?'FooBarBaz'
?
y
不是的函数z
,因此z
可以是任何东西,并且假设我们function
是纯函数,则不影响该函数的结果。(如果它z
作为全局变量访问,则它不是纯函数-这就是函数纯净的含义。)
阅读以下说明时,请牢记以上几点:
一个实例方法是函数是一个函数的一个实例。该函数隐式地接受该实例作为其参数,并且该实例由该函数使用以确定该函数的输出。
实例方法的内置示例为str.lower:
>>> 'ABC'.lower()
'abc'
str.lower
在字符串的实例上调用,并使用实例中包含的信息确定要返回的新字符串。
记住,在Python中,一切都是对象。这意味着该类是一个对象,并且可以作为参数传递给函数。
一类方法是一个函数,它是一个函数的类。它接受类作为其参数。
一个内置的示例是dict.fromkeys
:
>>> dict.fromkeys('ABC')
{'C': None, 'B': None, 'A': None}
该函数隐式地知道其自己的类,该函数使用该类来影响该函数的输出,并从可迭代对象中创建该类的新类。使用相同的方法时,OrderedDict会对此进行演示:
>>> from collections import OrderedDict
>>> OrderedDict.fromkeys('ABC')
OrderedDict([('A', None), ('B', None), ('C', None)])
class方法使用有关类的信息(而不是该类的实例)来影响要返回的类的类型。
您提到了“不知道其类”的方法-这是Python中的静态方法。它只是为了方便而附加到类对象上。它可以选择是另一个模块中的单独函数,但其调用签名将相同。
静态方法既不是类也不是对象的函数。
静态方法的内置示例是Python 3中的str.maketrans。
>>> str.maketrans('abc', 'bca')
{97: 98, 98: 99, 99: 97}
给定几个参数,它将创建一个字典,而不是其类的函数。
这很方便,因为str
它始终在全局名称空间中可用,因此您可以轻松地将其与translation函数一起使用:
>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
'bcrbabdbcrb'
在Python 2中,您必须从string
模块访问它:
>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'str' has no attribute 'maketrans'
>>> import string
>>> 'abracadabra'.translate(string.maketrans('abc', 'bca'))
'bcrbabdbcrb'
class AClass(object):
"""In Python, a class may have several types of methods:
instance methods, class methods, and static methods
"""
def an_instance_method(self, x, y, z=None):
"""this is a function of the instance of the object
self is the object's instance
"""
return self.a_class_method(x, y)
@classmethod
def a_class_method(cls, x, y, z=None):
"""this is a function of the class of the object
cls is the object's class
"""
return cls.a_static_method(x, y, z=z)
@staticmethod
def a_static_method(x, y, z=None):
"""this is neither a function of the instance or class to
which it is attached
"""
return x, y, z
让我们实例化:
>>> instance = AClass()
现在,实例可以调用所有方法:
>>> instance.an_instance_method('x', 'y')
('x', 'y', None)
>>> instance.a_static_method('x', 'y')
('x', 'y', None)
>>> instance.a_class_method('x', 'y')
('x', 'y', None)
但是该类通常不打算调用该实例方法,尽管希望它可以调用其他方法:
>>> AClass.a_class_method('x', 'y')
('x', 'y', None)
>>> AClass.a_static_method('x', 'y')
('x', 'y', None)
>>> AClass.an_instance_method('x', 'y')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an_instance_method() missing 1 required positional argument: 'y'
您必须显式传递实例才能调用实例方法:
>>> AClass.an_instance_method(instance, 'x', 'y')
('x', 'y', None)
MyClass(1,2,3)
,而是类似MyClass.get_special(1,2,3)
),而静态方法只是一种是正常的功能,无论如何都可以单独使用。
“实例方法”是将实例对象作为其第一个参数传递的方法,按照惯例,该参数称为self
。这是默认值。
“静态方法”是没有初始self
参数的方法。这是通过@staticmethod装饰器实现的。
“类方法”是一种方法,其中初始参数不是实例对象,而是类对象(有关 “类对象”的含义,请参见Python文档的此部分),按惯例称为cls
。这是通过@classmethod装饰器实现的。
C / C ++ / etc中术语“静态方法”的典型用法适用于Python“静态”和Python“类”方法,因为这两种类型的方法都缺少对实例的引用。在C / C ++ / etc中,方法通常可以隐式访问该类的所有非实例成员/方法,这可能就是为什么这种区别仅存在于Python / Ruby / etc等语言中的原因。
Class::staticMethod()
就可以了(只要不staticMethod()
因私有或其他原因而被禁止调用它)。