在Python中创建实例方法对象的不同方法

时间:2016-05-22 04:32:11

标签: python python-3.x methods attributes instance

Python 3.x语言参考描述了两种创建方法对象的方法:

  

当获取类的属性(可能通过该类的实例)时,如果该属性是用户定义的函数对象或类方法对象,则可以创建用户定义的方法对象。

     

当通过一个实例从类中检索用户定义的函数对象来创建实例方法对象时,其self属性是实例,并且方法对象被称为绑定。新方法的func属性是原始函数对象。

     

当通过从类或实例检索另一个方法对象来创建用户定义的方法对象时,行为与函数对象的行为相同,除了新实例的func属性不是原始方法对象。它的func属性。

     

调用实例方法对象时,将调用基础函数( func ),将类实例( self )插入参数列表前面。例如,当C是包含函数f()定义的类,而x是C的实例时,调用x.f(1)等同于调用C.f(x,1)。

     

当实例方法对象派生自类方法对象时,存储在 self 中的“类实例”实际上将是类本身,因此调用xf(1)或Cf(1 )相当于调用f(C,1),其中f是基础函数。

以不同的方式,有不同的__func____self__值,但现在我不太清楚这两种不同的方式,有人可以向我解释一下吗?

2 个答案:

答案 0 :(得分:1)

我不是100%确定我完全理解你的问题,但是看一个例子会有所帮助。首先,让我们创建一个在定义中具有函数的类:

>>> class Foo(object):
...   def method(self):
...     pass
... 
>>> f = Foo()
  

获取类的属性时(可能通过该类的实例),如果该属性是用户定义的函数对象或类方法对象,则可以创建用户定义的方法对象

好的,我们可以通过访问实例上的属性来创建方法对象(如果属性是函数)。在我们的设置中,f是类Foo的实例:

>>> type(f.method)
<class 'method'>

将其与访问上的method属性进行比较:

>>> type(Foo.method)
<class 'function'>
  

当通过一个实例从类中检索用户定义的函数对象来创建实例方法对象时,其__self__属性是实例,并且方法对象被称为绑定。新方法的__func__属性是原始函数对象。

这只是告诉我们实例方法中存在哪些属性。我们来看看:

>>> instance_method = f.method
>>> instance_method.__func__ is Foo.method
True
>>> instance_method.__self__ is f
True

因此我们看到方法对象具有__func__属性,该属性只是对实际Foo.method函数的引用。它还有一个__self__属性,它是对实例的引用。

  

调用实例方法对象时,将调用基础函数(func),将类实例(self)插入参数列表前面。例如,当C是包含函数f()定义的类,而x是C的实例时,调用x.f(1)等同于调用C.f(x,1)。

基本上,参考上面的例子,这只是说:If:

instance_method = f.method

然后:

instance_method(arg1, arg2)

执行以下操作:

instance_method.__func__(instance_method.__self__, arg1, arg2)

答案 1 :(得分:0)

出于完整性考虑,并作为@mgilson提供的出色答案的附录,我想解释一下原始问题中引用的其余两段。

首先让我们创建一个带有classmethod的类:

>>> class Foo(object):
...   @classmethod
...   def cmethod(cls):
...     pass
... 
>>> f = Foo()

现在第三段:

  

通过从类或实例中检索另一个方法对象创建用户定义的方法对象时,其行为与功能对象相同,不同之处在于新实例的func属性不是原始方法对象,而是其func属性。

这意味着:

>>> class_method = f.cmethod
>>> class_method.__func__ is Foo.cmethod.__func__
True
>>> class_method.__self__ is Foo
True

请注意,__self__是对Foo类的引用。最后一段:

  

当从类方法对象派生实例方法对象时,存储在self中的“类实例”实际上将是类本身,因此调用xf(1)或Cf(1)等效于调用f( C,1),其中f是基础函数。

这只是说以下所有内容都是等效的:

>>> f.cmethod(arg1, arg2)
>>> Foo.cmethod(arg1, arg2)
>>> f.cmethod.__func__(Foo, arg1, arg2)
>>> Foo.cmethod.__func__(Foo, arg1, arg2)
>>> f.cmethod.__func__(f.cmethod.__self__, arg1, arg2)
>>> Foo.cmethod.__func__(Foo.cmethod.__self__, arg1, arg2)