方法和功能之间的区别

这个问题在这里已经有了答案:

  • 方法和函数之间的区别33答案

  • 函数是Python中的可调用对象,即可以使用调用操作符调用(尽管其他对象可以通过实现__call__来模拟函数)。 例如:

    >>> def a(): pass
    >>> a
    <function a at 0x107063aa0>
    >>> type(a)
    <type 'function'>
    

    方法是一种特殊的功能类,可以被绑定或不被绑定。

    >>> 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'>
    

    当然,不能调用一个未绑定的方法(至少不需要直接将实例作为参数传递):

    >>> 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中,在大多数情况下,您不会注意到绑定方法,函数或可调用对象(即实现__call__的对象)或类构造函数之间的区别。 它们看起来都一样,它们只是有不同的命名约定。 在引擎盖下,这些物体可能看起来大不相同。

    这意味着一个绑定方法可以作为一个函数使用,这是使得Python如此强大的许多小事情之一

    >>> b = A().a
    >>> b()
    

    这也意味着,尽管len(...)str(...) (后者是一个类型构造函数)之间存在根本差异,但在深入挖掘之前,您将不会注意到这种差异:

    >>> len
    <built-in function len>
    >>> str
    <type 'str'>
    

    如果您仍然不明白方法是如何工作的,那么查看实现可能会澄清一些问题。 当引用不是数据属性的实例属性时,将搜索其类。 如果名称表示一个有效的类属性,它是一个函数对象,则通过打包(指向)实例对象和在抽象对象中一起找到的函数对象来创建方法对象:这是方法对象。 当使用参数列表调用方法对象时,会从实例对象和参数列表构造一个新参数列表,并使用此新参数列表调用函数对象。

    http://docs.python.org/2/tutorial/classes.html#method-objects

    仔细阅读本摘录。

    它的意思是 :

    1 /

    一个实例并不真正拥有一个对象作为其属性的方法。
    实际上,实例的__dict__中没有“方法”属性( __dict__是对象的名称空间)

    2 /

    事实上,一个实例在调用“method”属性时似乎有一个“方法”,这是由于一个进程,而不是一个实例名称空间内的方法对象的存在

    3 /

    而且,在类的名称空间中并不存在方法对象。

    但是与实例有所不同,因为在这样的调用完成时,必定会有某个地方导致真正的方法对象,但是不能?

    为了便于使用,所谓的类的“方法”属性实际上是在类的命名空间中作为属性的函数对象。
    也就是说,一对(函数,函数的标识符)是类的__dict__的成员,并且该属性允许解释器在执行方法调用时构造方法对象。

    4 /

    同样,一个类在调用“method”属性时似乎有一个“方法”的事实归因于一个过程,而不是类的命名空间内的方法对象的存在

    编辑我对此不再确定; 最后看

    5 /

    方法对象(不是“方法”对象;我的意思是真正的对象实际上是一个方法,在摘录中描述的内容)是在调用时创建的,它以前不存在。
    它是一种包装:它包装指向实例对象和方法所基于的函数对象的指针。

    所以,一种方法是基于一个函数的。 这个函数对于我来说是拥有上述“方法”的类的真正属性,因为这个函数实际上属于类的名字空间( __dict__ ):这个函数被描述为<function ......>当打印__dict__
    这个函数可以通过使用别名im_func__func__的方法对象来__func__ (参见下面的代码)

    我相信这些概念并不是很普遍的知道和理解。 但下面的代码证明了我所说的。

    class A(object):
        def __init__(self,b=0):
            self.b = b
        print 'The __init__ object :n',__init__
    
        def addu(self):
            self.b = self.b + 10
        print 'nThe addu object :n',addu
    
    
    print 'nThe A.__dict__  items :n',
    print 'n'.join('  {0:{align}11}  :  {1}'.format(*it,align='^')
                    for it in A.__dict__.items())
    a1 = A(101)
    a2 = A(2002)
    
    print 'nThe a1.__dict__  items:'
    print 'n'.join('  {0:{align}11}  :  {1}'.format(*it,align='^')
                    for it in a1.__dict__.items())
    
    print 'nThe a2.__dict__  items:'
    print 'n'.join('  {0:{align}11}  :  {1}'.format(*it,align='^')
                    for it in a2.__dict__.items())
    
    print 'nA.addu.__func__ :',A.addu.__func__
    print id(A.addu.__func__),'==',hex(id(A.addu.__func__))
    print
    
    print 'A.addu :n  ',
    print A.addu,'n  ',id(A.addu),'==',hex(id(A.addu))
    
    print 'a1.addu :n  ',
    print a1.addu,'n  ',id(a1.addu),'==',hex(id(a1.addu))
    print 'a2.addu :n  ',
    print a2.addu,'n  ',id(a2.addu),'==',hex(id(a2.addu))
    
    a2.addu()
    print 'na2.b ==',a2.b
    
    print 'nThe A.__dict__  items :n',
    print 'n'.join('  {0:{align}11}  :  {1}'.format(*it,align='^')
                    for it in A.__dict__.items())
    

    结果

    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__    :  <attribute '__dict__' of 'A' objects>
      __weakref__  :  <attribute '__weakref__' of 'A' objects>
        __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__    :  <attribute '__dict__' of 'A' objects>
      __weakref__  :  <attribute '__weakref__' of 'A' objects>
        __doc__    :  None
       __init__    :  <function __init__ at 0x011E54B0>
    

    编辑

    有什么让我感到困扰,我不知道这个问题的深层内涵:

    上面的代码显示A.addua1.addua2.addu都是具有唯一标识的相同方法对象。
    然而A.addu被说成是一种无约束的方法,因为它没有关于特定实例的任何信息,
    并且a1.addua2.addu被称为绑定方法,因为每个人都有指定必须与该方法的操作有关的实例的信息。
    从逻辑上来说,对我而言,这意味着这三种情况下的方法应该不同。

    但是三者的身份是相同的,而且这个身份不同于该方法所基于的功能的身份。
    这导致了这样一个结论:该方法实际上是一个生活在记忆中的对象,并且它不会从一个实例调用到另一个实例的另一个调用。

    但是 ,即使在创建实例并调用“method” addu()之后,打印该类的名称空间__dict__ ,该名称空间不会公开可以识别的方法对象的新对象,而不同于addu函数。

    这是什么意思 ?
    它给我的印象是,只要创建了一个方法对象,它就不会被销毁,而是存在于内存(RAM)中。
    但它隐藏起来,只有形成实际操作者的过程知道如何以及在哪里找到它。
    这个隐藏的对象,即真实的方法对象,必须能够将引用更改为该函数必须应用到的实例,或者如果将其作为未绑定方法调用,则引用None 。 这就是我所认为的,但这只是脑力激荡的假设。

    有人知道这个讯问有什么?


    为了回答这个问题,可以认为调用.upper.lower函数是正确的,因为实际上它们是基于功能的,而.lower每个类的方法。

    但是,下面的结果是特殊的,可能是因为它们是内建的方法/函数,而不是用户的方法/函数,就像我的代码中那样。

    x = 'hello'
    print x.upper.__func__
    

    结果

        print x.upper.__func__
    AttributeError: 'builtin_function_or_method' object has no attribute '__func__'
    

    基本上,是的,Python确实区分了它们,但在Python中,将方法视为函数的子集是很常见的。 方法与类或实例关联,而“独立函数”则不是。 作为一种方法的东西也是一种功能,但可能有不是方法的功能。

    正如Jon Clements在他的评论中提到的那样,这个区别并不像C ++那样铁定。 独立函数可以在运行时“转换”为方法,并且可以将方法分配给变量,使得它们的有效行为与独立函数无异。 所以方法和功能之间的界限是可渗透的。

    链接地址: http://www.djcxy.com/p/17305.html

    上一篇: Difference between methods and functions

    下一篇: Difference between Method and Function?