Home  >  Q&A  >  body text

python3.x - Python 如何通过类方法创建实例方法?

下面是 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.

PHPzPHPz2742 days ago960

reply all(2)I'll reply

  • 黄舟

    黄舟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.

    DemoCategory:

    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:

    1. Python reference for foo,會產生一個 一般的 function,這個 function 會被 Demo.foo.

    2. 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.

    3. 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 selfclass 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:

    1. Python for bar, will generate Demo.bar ,他是一個來自於 class method objectbound method object,原本 Demo.bar 就跟 Demo.foo 一樣是個一般的 Python function,但是透過修飾器(@classmethod 修飾器),他成為了一個 bound method object,若要觀察原本的 general function,只能在 Demo.bar.__func__ 中看到,同時他綁定了 Demo 類,所以 Demo.bar.__self__ 會參考到 Demo class.

    2. 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:

    1. In Python3, there are two types of funcitons in class, one is a general function object, and the other is a bound method object

    2. 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

    3. When the
    4. 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

    reply
    0
  • 大家讲道理

    大家讲道理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)
    

    reply
    0
  • Cancelreply