下面是 Python 3.x language reference 中的一段话,大意是理解的,不过写不出一个这样的示例,求大神给个与这段话一致的示例:
When an instance method object is derived from a class method object, the “class instance” stored in self will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function.
黄舟2017-04-17 17:55:52
In fact, you will understand this part by doing your own experiments.
Let’s start from the original text and divide it into two paragraphs to discuss. The first paragraph says:
When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f( ), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1).
The first paragraph of the original text says that when a instance method object
被調用時,__func__
的第一個參數先代入 class instance
is called, then it gives an example:
x.f(1) == C.f(x,1) # x is an instance of C
We use the following example to illustrate, here we have a class Demo
,他底下有一個 function foo
和 function bar
.
Demo
Category:
class Demo:
def foo(self, *args):
return 'Call foo by instance' + repr(self) + 'with args' + repr(args)
@classmethod
def bar(cls, *args):
return 'Call bar by class ' + repr(cls) + 'with args' + repr(args)
Actually:
Python reference for foo
,會產生一個 一般的 function,這個 function 會被 Demo.foo
.
When we write demo.foo
的時候,Python 會即時創造一個 bound method object: demo.foo
,這個 method object 是個綁定的 method,綁定甚麼呢? 當然就是綁定 demo
這個 instance,所以 demo.foo.__self__
會參考到 demo
, 同時 Python 也會把 Demo.foo
記在 demo.foo.__func__
in.
So treat this demo.foo
被呼叫的時候(demo.foo(1,2,3)
),他其實會去呼叫 demo.foo.__func__
,並且以 demo.foo.__self__
(其實也就是 demo
self) as the first parameter.
If we use the class we wrote to show it, his example becomes:
x.f(1) == C.f(x, 1)
demo.foo(1) == Demo.foo(demo, 1) == demo.foo.__func__(demo.foo.__self__, 1)
Look at the code:
demo = Demo()
print('=== Demo start ===\n')
print('demo.foo', ':', demo.foo)
print(' [type ] ', type(demo.foo))
print(' [demo.foo.__self__] ', demo.foo.__self__)
print(' [demo.foo.__func__] ', demo.foo.__func__)
print(' [demo.foo(1,2,3) ] ', demo.foo(1,2,3))
print()
print('Demo.foo', ':', Demo.foo)
print(' [type ] ', type(Demo.foo))
print(' [Demo.foo(demo, 1,2,3)] ', Demo.foo(demo, 1,2,3))
print()
print('demo.foo.__func__', ':', demo.foo.__func__,)
print(' [type ] ', type(demo.foo.__func__))
print(' [demo.foo.__func__(demo, 1,2,3)] ', demo.foo.__func__(demo, 1,2,3))
print()
print('Demo.foo is demo.foo.__func__ --> ', Demo.foo is demo.foo.__func__)
Test results:
=== Demo start ===
demo.foo : <bound method Demo.foo of <__main__.Demo object at 0x7f413db47fd0>>
[type ] <class 'method'>
[demo.foo.__self__] <__main__.Demo object at 0x7f413db47fd0>
[demo.foo.__func__] <function Demo.foo at 0x7f413db41840>
[demo.foo(1,2,3) ] Call foo by instance<__main__.Demo object at 0x7f413db47fd0>with args(1, 2, 3)
Demo.foo : <function Demo.foo at 0x7f413db41840>
[type ] <class 'function'>
[Demo.foo(demo, 1,2,3)] Call foo by instance<__main__.Demo object at 0x7f413db47fd0>with args(1, 2, 3)
demo.foo.__func__ : <function Demo.foo at 0x7f413db41840>
[type ] <class 'function'>
[demo.foo.__func__(demo, 1,2,3)] Call foo by instance<__main__.Demo object at 0x7f413db47fd0>with args(1, 2, 3)
Demo.foo is demo.foo.__func__ --> True
Then watch the second paragraph:
When an instance method object is derived from a class method object, the “class instance” stored in self will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C ,1) where f is the underlying function.
The main idea of the second paragraph is that when the instance method object comes from the class method object, the self
class instance that exists in will be the class itself. Then another example is given:
x.f(1) == C.f(1) == f(C,1) # x is an instance of C
We also use examples to illustrate:
Python for bar, will generate Demo.bar
,他是一個來自於 class method object 的 bound method object,原本 Demo.bar
就跟 Demo.foo
一樣是個一般的 Python function,但是透過修飾器(@classmethod
修飾器),他成為了一個 bound method object,若要觀察原本的 general function,只能在 Demo.bar.__func__
中看到,同時他綁定了 Demo
類,所以 Demo.bar.__self__
會參考到 Demo
class.
So when Demo.bar
被呼叫的時候(Demo.bar(1)
),,他其實會去呼叫 Demo.bar.__func__
,並且以 Demo.bar.__self__
(其實也就是 Demo
itself) is treated as the first parameter.
If we use the class we wrote to show it, his example becomes:
x.f(1) == C.f(1) == f(C, 1)
demo.bar(1) == Demo.bar(1) == Demo.bar.__func__(Demo, 1) == Demo.bar.__func__(Demo.bar.__self__, 1)
Test code:
demo = Demo()
print('=== Demo start ===\n')
print('Demo.bar', ':', Demo.bar)
print(' [type ] ', type(Demo.bar))
print(' [Demo.bar.__self__] ', Demo.bar.__self__)
print(' [Demo.bar.__func__] ', Demo.bar.__func__)
print(' [Demo.bar(1,2,3) ] ', Demo.bar(1,2,3))
print()
print('Demo.bar(1) ', Demo.bar(1))
print('demo.bar(1) ', demo.bar(1))
print('Demo.bar.__func__(Demo, 1)', Demo.bar.__func__(Demo, 1))
Test results:
=== Demo start ===
Demo.bar : <bound method type.bar of <class '__main__.Demo'>>
[type ] <class 'method'>
[Demo.bar.__self__] <class '__main__.Demo'>
[Demo.bar.__func__] <function Demo.bar at 0x7f413db41950>
[Demo.bar(1,2,3) ] Call bar by class <class '__main__.Demo'>with args(1, 2, 3)
Demo.bar(1) Call bar by class <class '__main__.Demo'>with args(1,)
demo.bar(1) Call bar by class <class '__main__.Demo'>with args(1,)
Demo.bar.__func__(Demo, 1) Call bar by class <class '__main__.Demo'>with args(1,)
Conclusion:
In Python3, there are two types of funcitons in class, one is a general function object, and the other is a bound method object
Instance method is a method object composed of a general function bound to an instance, and class mehtod is a method object composed of a general function bound to a class
bound method is called, it actually calls the original function (recorded in __func__
中),但會以綁定的對象作為第一個參數(記在 __self__
).
References:
Difference between methods and functions
Different way to create an instance method object in Python
大家讲道理2017-04-17 17:55:52
# -*- coding: utf-8 -*-
class Parent:
@classmethod
# 这里就相当于是f
def foo(cls, arg):
print("foo called, " + str(cls) + " " + str(arg))
class Child(Parent):
pass
# 创建一个子类的实例
a = Child()
# 调用类方法,可见将对象传递给类方法时,会调用类方法,并且自动绑定了类
a.foo(1)
# 结果和上述一样
Child.foo(1)