Difference between methods and functions, in Python compared to C++
我正在编写关于Python的代码学院教程,我对方法和函数的定义有点困惑。从教程中:
You already know about some of the built-in functions we've used on (or to create) strings, such as
.upper() ,.lower() ,str() , andlen() .
来自C++,我认为EDOCX1 0和EDCOX1,1称为方法,EDOCX1,2,EDCX1,3个函数。在本教程中,这些术语似乎可以互换使用。
Python区分C++中的方法和函数吗?
与方法和函数之间的区别不同,我在询问关于Python的详细信息。术语"方法"和"函数"似乎并不总是遵循链接问题的公认答案中给出的定义。
函数是python中的可调用对象,也就是说,可以使用调用操作符调用(尽管其他对象可以通过实现
1 2 3 4 5 | >>> def a(): pass >>> a <function a at 0x107063aa0> >>> type(a) <type 'function'> |
方法是一个特殊的函数类,可以绑定或取消绑定。
1 2 3 4 5 6 7 8 9 10 11 | >>> class A: ... def a(self): pass >>> A.a <unbound method A.a> >>> type(A.a) <type 'instancemethod'> >>> A().a <bound method A.a of <__main__.A instance at 0x107070d88>> >>> type(A().a) <type 'instancemethod'> |
当然,不能调用未绑定的方法(至少不能在不将实例作为参数传递的情况下直接调用):
1 2 3 4 | >>> A.a() Traceback (most recent call last): File"<stdin>", line 1, in <module> TypeError: unbound method a() must be called with A instance as first argument (got nothing instead) |
在Python中,在大多数情况下,您不会注意到绑定方法、函数或可调用对象(即实现
这意味着绑定方法可以用作函数,这是使Python如此强大的许多小东西之一。
1 2 | >>> b = A().a >>> b() |
这也意味着,尽管
1 2 3 4 | >>> len <built-in function len> >>> str <type 'str'> |
If you still don’t understand how methods work, a look at the
implementation can perhaps clarify matters. When an instance attribute
is referenced that isn’t a data attribute, its class is searched. If
the name denotes a valid class attribute that is a function object, a
method object is created by packing (pointers to) the instance object
and the function object just found together in an abstract object:
this is the method object. When the method object is called with an
argument list, a new argument list is constructed from the instance
object and the argument list, and the function object is called with
this new argument list.Ok.
http://docs.python.org/2/tutorial/classes.html#method-objects
Ok.
仔细阅读这段摘录。好的。
它的意思是:好的。
1)一个实例并不真正拥有一个对象,而该对象是一个将成为其属性的方法。实际上,实例的
2)当调用"method"属性时,一个实例似乎有一个"method",这是由于一个进程,而不是实例的命名空间中存在一个方法对象。好的。
3)另外,在类的名称空间中还没有真正的方法对象。好的。
但是实例有一个区别,因为当这样的调用完成时,一定有某种东西会导致一个真正的方法对象,不是吗?好的。
所谓的类的"方法"属性,为了便于使用,实际上是一个函数对象,它是类名称空间中的属性。也就是说,一对(函数的标识符,函数)是类的
4)同样,当调用"method"属性时,类似乎具有"method"这一事实是由于进程,而不是类的命名空间中存在方法对象。好的。
EDIT I'm no more sure of that; see at the end
Ok.
5)方法对象(不是"方法"对象;我的意思是实际对象实际上是方法`,摘录中描述的内容)是在调用时创建的,它以前不存在。它是一种包装器:它打包指向实例对象和方法所基于的函数对象的指针。好的。
所以,一个方法是基于一个函数的。对于我来说,这个函数是持有上述"方法"的类的真实属性,因为这个函数实际上属于类的名称空间(
.好的。
我相信这些概念不是很常见和理解。但是下面的代码证明了我所说的。好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | class A(object): def __init__(self,b=0): self.b = b print 'The __init__ object : ',__init__ def addu(self): self.b = self.b + 10 print ' The addu object : ',addu print ' The A.__dict__ items : ', print ' '.join(' {0:{align}11} : {1}'.format(*it,align='^') for it in A.__dict__.items()) a1 = A(101) a2 = A(2002) print ' The a1.__dict__ items:' print ' '.join(' {0:{align}11} : {1}'.format(*it,align='^') for it in a1.__dict__.items()) print ' The a2.__dict__ items:' print ' '.join(' {0:{align}11} : {1}'.format(*it,align='^') for it in a2.__dict__.items()) print ' A.addu.__func__ :',A.addu.__func__ print id(A.addu.__func__),'==',hex(id(A.addu.__func__)) print 'A.addu : ', print A.addu,' ',id(A.addu),'==',hex(id(A.addu)) print 'a1.addu : ', print a1.addu,' ',id(a1.addu),'==',hex(id(a1.addu)) print 'a2.addu : ', print a2.addu,' ',id(a2.addu),'==',hex(id(a2.addu)) a2.addu() print ' a2.b ==',a2.b print ' The A.__dict__ items : ', print ' '.join(' {0:{align}11} : {1}'.format(*it,align='^') for it in A.__dict__.items()) |
结果好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | The __init__ object : <function __init__ at 0x011E54B0> The addu object : <function addu at 0x011E54F0> The A.__dict__ items : __module__ : __main__ addu : <function addu at 0x011E54F0> __dict__ : __weakref__ : __doc__ : None __init__ : <function __init__ at 0x011E54B0> The a1.__dict__ items: b : 101 The a2.__dict__ items: b : 2002 A.addu.__func__ : <function addu at 0x011E54F0> 18765040 == 0x11e54f0 A.addu : <unbound method A.addu> 18668040 == 0x11cda08 a1.addu : <bound method A.addu of <__main__.A object at 0x00CAA850>> 18668040 == 0x11cda08 a2.addu : <bound method A.addu of <__main__.A object at 0x011E2B90>> 18668040 == 0x11cda08 a2.b == 2012 The A.__dict__ items : __module__ : __main__ addu : <function addu at 0x011E54F0> __dict__ : __weakref__ : __doc__ : None __init__ : <function __init__ at 0x011E54B0> |
.好的。编辑
有什么事困扰着我,我不知道这个问题的深层次:好的。
以上代码表明,
但三者的同一性是相同的,而且这个同一性不同于方法所基于的函数的同一性。它得出的结论是,该方法实际上是内存中的一个对象,并且它不会从一个实例的一个调用更改为另一个实例的另一个CAL。好的。
但是,打印类的名称空间
这是什么意思?它给我的印象是,一旦创建了一个方法对象,它就不会被破坏,而是存在于内存(RAM)中。但它是隐藏的,只有形成介子功能的过程才知道如何和在哪里找到它。此隐藏对象(real method对象)必须能够更改对必须应用函数的实例的引用,或者如果作为未绑定方法调用,则可以更改对
有人知道这个审问吗?好的。
为了回答这个问题,可以认为调用
但是,下面的结果是特殊的,可能是因为它们是内置的方法/函数,而不是我的代码中用户的方法/函数。好的。
1 2 | x = 'hello' print x.upper.__func__ |
结果好的。
1 2 | print x.upper.__func__ AttributeError: 'builtin_function_or_method' object has no attribute '__func__' |
好啊。
在以下类定义中:
1 2 3 4 | class MyClass: """A simple example class""" def f(self): return 'hello world' |
- 班级:MyClass
- 函数:f-()
- 方法:无(实际不适用)
让我们创建上述类的实例。我们将通过将
1 | x = MyClass() |
在这里,
- 功能:无
- 方法:x. f-()
别忘了,当我们把x分配给myclass()时,
基本上,是的,python确实区分了它们,但在python中,通常将方法视为函数的子集。方法与类或实例关联,而"独立函数"则不关联。一个方法也是一个函数,但也有一些函数不是方法。
正如Jon Clements在他的评论中提到的,这个区别并不像C++中那么明显。独立函数可以在运行时"转换"为方法,并且可以将方法分配给变量,使它们的行为与独立函数没有任何不同。所以方法和函数之间的边界是可渗透的。