Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Instancemethod还是function?_Python_Python 2.7 - Fatal编程技术网

Python Instancemethod还是function?

Python Instancemethod还是function?,python,python-2.7,Python,Python 2.7,今天,我定义了一个类,只是为了测试接下来的内容: class B(object): def p(self): print("p") 后来我做了这个: >>> type(B.__dict__['p']) <type 'function'> >>> type(B.p) <type 'instancemethod'> 好的,到目前为止还不错,类型在两个resultsfunction中,但当我尝试时: >>

今天,我定义了一个类,只是为了测试接下来的内容:

class B(object):
    def p(self):
        print("p")
后来我做了这个:

>>> type(B.__dict__['p'])
<type 'function'>
>>> type(B.p)
<type 'instancemethod'>
好的,到目前为止还不错,类型在两个results
function
中,但当我尝试时:

>>> B.p
<unbound method B.p>
>>> type(B.p)
<type 'instancemethod'>
那么,为什么呢?难道
B.p
B.\uu dict\uuu['p']
不是同一个对象吗

不,属性访问是神奇的;当通过属性名访问用户定义的方法时,会返回绑定方法或未绑定方法(这在Python 3中有所改变;不再有任何未绑定方法;如果通过类对象访问实例方法,则会得到一个常规函数);直接通过dict访问绕过了这个魔法

什么?!,为什么?unbound方法和instancemethod?是否相同?为什么有两个不同的名字

用户定义的方法属于
instancemethod
类型,除非它是用
@classmethod
@staticmethod
装饰器定义的。它可以是绑定的instancemethod(当作为实例的属性访问时)或未绑定的方法(当作为类的属性访问时)


(请参阅的“用户定义的方法”部分以获取解释。)

这是一个非常好的问题

要澄清一些事情:

  • 当通过其类(例如
    B.p
    )访问方法名时,称其为未绑定
  • 否则,通过其类实例(例如
    B().p
    )访问该方法称为绑定
  • 绑定和未绑定之间的主要区别在于,如果绑定,则第一个参数将隐式地是调用类的实例。这就是为什么我们在定义每个方法时必须将
    self
    作为第一个参数添加到每个方法中。解除绑定时,必须显式传递要应用该方法逻辑的类的实例

    例如:

    class B(object):
        def foo(self):
            print 'ok'
    
    >>>B().foo()
    ok
    >>>B.foo()
    Exception, missing an argument.
    >>>B.foo(B())
    ok
    
    这是绑定和未绑定的基本解释。现在关于
    \uuuu dict\uuuu
    的古怪。Python中的任何对象都可以定义
    \uuuu get\uuuuu
    \uuu set\uuuuu
    方法,当它们是类中的属性时,这些方法控制对它们的访问。这些被称为描述符

    简单地说,当您通过类的实例或类访问类的属性(property)时,Python不会直接返回对象,而是调用
    \uuuuuuu get\uuuuu
    \uuu set\uuuu
    方法,然后返回一个方便使用的对象

    Python中的函数重写了这个
    \uuuuu get\uuu
    方法。因此,当您发出
    B.foo
    B().foo
    时,它会返回一个
    instancemethod
    类型,它是
    函数
    类型的包装(隐式传递
    self
    作为第一个参数的包装)。当您通过原始类的字典访问函数时,不会调用
    \uuuu get\uuuu
    ,因为您不是作为类的属性访问它们,因此返回值是原始函数

    关于这个话题有很多要说的,我试着给这么一个聪明的话题一个非常简单的答案。您可以在Guido的博客文章中找到明确的信息,非常推荐

    更新:关于上一个示例:

    >>> B.p
    <unbound method B.p>
    >>> type(B.p)
    <type 'instancemethod'>
    
    >>B.p
    >>>类型(B.p)
    
    请注意,在Python的解释器中,B.p实际上并不打印对象的类型,而是打印对象的方法。您可以通过执行打印B.p.\uuuu repr\uuuu()并查看结果是否相同来检查:)

    Python充满了间接和委托,这就是它如此灵活的原因

    希望这能澄清一点

    那么,为什么呢?B.p和B.dict是同一个对象吗


    显然,他们不是。阅读以下内容:了解更深入的解释。

    我不知道为什么有人否决了这个问题。@PauloBu好吧,现在我们是两个人了!注意,(un)bound这个词已经是过去分词了,所以(un)bounded是过去分词nonsense@Eric谢谢你,很抱歉。英语不是我的母语:(更让人困惑的是,实际上有一个词unbound,意思是“无边界”:没有边界或边缘的东西。也许你是这么想的。@PeterWestlake LOL我不这么认为。我指的是函数的状态。我认为unbound是可以的。非常感谢:)@xndrme:添加了关于交互式解释器输出的最后一句话。“属性访问是魔术”:好吧,就像所有的“魔术”一样,只有在你学会技巧之前,它似乎才是魔术;)。
    class B(object):
        def foo(self):
            print 'ok'
    
    >>>B().foo()
    ok
    >>>B.foo()
    Exception, missing an argument.
    >>>B.foo(B())
    ok
    
    >>> B.p
    <unbound method B.p>
    >>> type(B.p)
    <type 'instancemethod'>