任何人都可以用非常简单的术语向我解释Python中的“方法”是什么?
问题是在许多针对初学者的Python教程中,这个词的使用方式就像初学者已经知道Python上下文中的方法是什么。我当然很熟悉这个词的一般含义,但是我不知道这个词在Python中的含义。因此,请向我解释“ Pythonian”方法的全部含义。
一些非常简单的示例代码将非常值得赞赏,因为一张图片值得一千个单词。
任何人都可以用非常简单的术语向我解释Python中的“方法”是什么?
问题是在许多针对初学者的Python教程中,这个词的使用方式就像初学者已经知道Python上下文中的方法是什么。我当然很熟悉这个词的一般含义,但是我不知道这个词在Python中的含义。因此,请向我解释“ Pythonian”方法的全部含义。
一些非常简单的示例代码将非常值得赞赏,因为一张图片值得一千个单词。
Answers:
这是一个函数,它是一个类的成员:
class C:
def my_method(self):
print("I am a C")
c = C()
c.my_method() # Prints("I am a C")
就那么简单!
(还有一些替代方法,允许您控制类和函数之间的关系。但是我从您的问题中猜测,您不是在问这个问题,而只是在询问基本问题。)
self
。
self
按惯例被调用)。
方法是将类实例作为其第一个参数的函数。方法是类的成员。
class C:
def method(self, possibly, other, arguments):
pass # do something here
正如您想知道它在Python中的具体含义一样,您可以区分绑定方法和非绑定方法。在Python中,所有函数(以及方法也是如此)都是可以传递和“玩”的对象。因此,未绑定和绑定方法之间的区别是:
1)绑定方法
# Create an instance of C and call method()
instance = C()
print instance.method # prints '<bound method C.method of <__main__.C instance at 0x00FC50F8>>'
instance.method(1, 2, 3) # normal method call
f = instance.method
f(1, 2, 3) # method call without using the variable 'instance' explicitly
绑定方法是属于类实例的方法。在此示例中,instance.method
绑定到名为的实例instance
。每次调用该绑定方法时,该实例都会自动作为第一个参数传递-self
按照惯例进行调用。
2)未绑定方法
print C.method # prints '<unbound method C.method>'
instance = C()
C.method(instance, 1, 2, 3) # this call is the same as...
f = C.method
f(instance, 1, 2, 3) # ..this one...
instance.method(1, 2, 3) # and the same as calling the bound method as you would usually do
当您访问C.method
(类内部而不是实例内部的方法)时,您将获得未绑定的方法。如果要调用它,则必须将实例作为第一个参数传递,因为该方法未绑定到任何实例。
知道了这种差异,您可以将函数/方法用作对象,就像传递方法一样。作为一个示例用例,想象一个API,它可以定义一个回调函数,但是您想提供一个方法作为回调函数。没问题,只要self.myCallbackMethod
作为回调传递,它将以实例作为第一个参数自动调用。这在像C ++这样的静态语言中是不可能的(或仅在具有欺骗性的情况下)。
希望你明白了;)我认为这是关于方法基础的所有知识。您还可以阅读有关classmethod
和staticmethod
装饰器的更多信息,但这是另一个主题。
在Python中,由于对象的类型,方法是可用于给定对象的函数。
例如,如果您创建my_list = [1, 2, 3]
,则append
可以应用该方法,my_list
因为它是一个Python列表:my_list.append(4)
。所有列表之所以具有append
方法,仅仅是因为它们是列表。
再举一个例子,如果您创建my_string = 'some lowercase text'
,则仅因为它是Python字符串,upper
就可以应用该方法my_string
:my_string.upper()
。
列表没有upper
方法,字符串没有append
方法。为什么?因为只有针对特定对象明确定义了方法,方法才存在于特定对象中,并且Python的开发人员(到目前为止)决定这些特定对象不需要那些特定方法。
要调用方法,格式为object_name.method_name()
,并且该方法的所有参数都列在括号内。该方法隐式作用于要命名的对象,因此某些方法没有任何声明的自变量,因为对象本身是唯一必需的自变量。例如,my_string.upper()
没有任何列出的参数,因为唯一需要的参数是对象本身my_string
。
一个常见的混淆点涉及以下方面:
import math
math.sqrt(81)
是对象sqrt
的方法math
吗?否。这是sqrt
从math
模块中调用函数的方式。使用的格式是module_name.function_name()
,而不是object_name.method_name()
。一般情况下,只有这样才能在两种格式之间区分(视觉)是看在代码的其余部分,看看部分的时间段之前(math
,my_list
,my_string
)被定义为一个对象或一个模块。
抱歉,但是-在我看来-RichieHindle关于说这种方法是完全正确的...
这是一个函数,它是类的成员。
这是成为类成员的函数的示例。从那时起,它就充当类的方法。让我们从空类和带有一个参数的普通函数开始:
>>> class C:
... pass
...
>>> def func(self):
... print 'func called'
...
>>> func('whatever')
func called
现在,我们将一个成员添加到C
类中,该成员是对该函数的引用。之后,我们可以创建该类的实例,并像在类内部定义它一样调用其方法:
>>> C.func = func
>>> o = C()
>>> o.func()
func called
我们还可以使用另一种方法来调用该方法:
>>> C.func(o)
func called
该o.func
甚至体现方式相同类方法:
>>> o.func
<bound method C.func of <__main__.C instance at 0x000000000229ACC8>>
我们可以尝试反向方法。让我们定义一个类并将其方法用作函数:
>>> class A:
... def func(self):
... print 'aaa'
...
>>> a = A()
>>> a.func
<bound method A.func of <__main__.A instance at 0x000000000229AD08>>
>>> a.func()
aaa
到目前为止,它看起来相同。现在,函数窃取:
>>> afunc = A.func
>>> afunc(a)
aaa
事实是该方法不接受“任何”参数:
>>> afunc('whatever')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method func() must be called with A instance as first
argument (got str instance instead)
恕我直言,这不是反对method是属于class成员的函数的参数。
后来发现了亚历马尔泰利的答案,基本上也是这么说的。抱歉,如果您认为它是重复的:)
http://docs.python.org/2/tutorial/classes.html#method-objects
通常,方法在绑定之后立即被调用:
x.f()
在MyClass示例中,这将返回字符串“ hello world”。但是,不必立即调用方法:xf是方法对象,可以立即存储并在以后调用。例如:
xf = x.f while True: print xf()
将继续打印问候世界,直到时间结束。
调用方法时到底发生了什么?您可能已经注意到,即使f()的函数定义指定了参数,上面的xf()也是在没有参数的情况下调用的。争论发生了什么?当没有任何参数调用需要参数的函数时,即使确实未使用该参数,Python当然也会引发异常。
实际上,您可能已经猜到了答案:方法的特殊之处在于,对象作为函数的第一个参数传递。在我们的示例中,调用xf()完全等同于MyClass.f(x)。通常,调用带有n个参数列表的方法等效于调用带有参数列表的函数,该参数列表是通过在第一个参数之前插入方法的对象而创建的。
如果您仍然不了解方法的工作方式,那么看一下实现也许可以澄清问题。当引用的实例属性不是数据属性时,将搜索其类。如果名称表示作为函数对象的有效类属性,则通过将实例对象和刚在抽象对象中一起找到的函数对象打包(指向)来创建方法对象:这是方法对象。当使用实参列表调用方法对象时,将从实例对象和实参列表构造一个新的实参列表,并使用该新的实参列表来调用函数对象。
如果您认为对象与名词相似,那么方法与动词相似。在对象(即字符串或列表)之后立即使用方法,以将方法的操作应用于该对象。
要了解方法,您必须首先考虑面向对象的编程:让我们把汽车当成一类。所有汽车都有一些共同点,并且使它们与众不同,例如,所有汽车都有4个轮子,车门,一个方向盘....但是您的每辆汽车(我们称之为my_toyota)是红色的,从0到60 5.6s此外,汽车当前位于我家中,门已锁定,后备箱是空的……所有这些都是my_toyota实例的属性。your_honda可能正在路上,到处都是杂货...
但是,您可以使用汽车进行某些操作。您可以开车,可以开门,也可以装载。您可以用汽车执行的操作就是汽车的方法,它们会更改特定实例的属性。
作为伪代码,您将执行以下操作:
my_toyota.drive(shop)
将位置从我的家更改为商店,或者
my_toyota.load([milk, butter, bread]
这样,行李箱就装满了[牛奶,黄油,面包]。
因此,这种方法实际上是充当对象一部分的功能:
class Car(vehicle)
n_wheels = 4
load(self, stuff):
'''this is a method, to load stuff into the trunk of the car'''
self.open_trunk
self.trunk.append(stuff)
self.close_trunk
该代码将是:
my_toyota = Car(red)
my_shopping = [milk, butter, bread]
my_toyota.load(my_shopping)