recherche

Maison  >  Questions et réponses  >  le corps du texte

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.

PHPzPHPz2804 Il y a quelques jours977

répondre à tous(2)je répondrai

  • 黄舟

    黄舟2017-04-17 17:55:52

    En fait, vous comprendrez cette partie en faisant vos propres expériences.


    Partons du texte original et divisons-le en deux paragraphes pour en discuter. Le premier paragraphe dit :

    Lorsqu'un objet méthode d'instance est appelé, la fonction sous-jacente (__func__) est appelée, en insérant l'instance de classe (__self__) devant la liste d'arguments. Par exemple, lorsque C est une classe qui contient une définition pour. une fonction f(), et x est une instance de C, appeler x.f(1) équivaut à appeler C.f(x, 1).

    Le premier paragraphe de l'article original dit que lorsqu'un instance method object est appelé, le premier paramètre de __func__ est d'abord substitué dans class instance puis appelé, puis donne un exemple :

    x.f(1) == C.f(x,1)  # x is an instance of C

    Nous utilisons l'exemple suivant pour illustrer. Ici, nous avons une classe Demo, qui a une fonction foo et une fonction bar en dessous.

    DemoCatégorie :

    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)

    En fait :

    1. Python pour foo générera une fonction générale, qui sera référencée par Demo.foo.

    2. Lorsque nous écrivons demo.foo, Python créera instantanément un objet méthode lié : demo.foo Cet objet méthode est une méthode liée. À quoi est-il lié ? pour lier l'instance demo, donc demo.foo.__self__ fera référence à demo, et Python enregistrera également Demo.foo dans demo.foo.__func__.

    3. Ainsi, lorsque ce demo.foo est appelé (demo.foo(1,2,3)), il appellera en fait demo.foo.__func__ et utilisera demo.foo.__self__ (en fait demo lui-même) comme premier paramètre.

    S'il est montré en utilisant la classe que nous avons écrite, son exemple devient :

       x.f(1)   ==    C.f(x, 1) 
    demo.foo(1) == Demo.foo(demo, 1) == demo.foo.__func__(demo.foo.__self__, 1) 

    Regardez le 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__)

    Résultats des tests :

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

    Lisez le deuxième paragraphe :

    Lorsqu'un objet méthode d'instance est dérivé d'un objet méthode de classe, « l'instance de classe » stockée dans self sera en fait la classe elle-même, de sorte qu'appeler x.f(1) ou C.f(1) équivaut à appelant f(C,1) où f est la fonction sous-jacente.

    L'idée principale du deuxième paragraphe est que lorsque l'objet méthode d'instance provient de l'objet méthode de classe, la selfinstance de classe qui existe dans sera la classe lui-même, puis un autre exemple :

    x.f(1) == C.f(1) == f(C,1)  # x is an instance of C

    Nous utilisons également des exemples pour illustrer :

    1. Python générera Demo.bar pour bar, qui est un objet de méthode lié à partir de objet de méthode de classe À l'origine, Demo.bar est exactement comme Demo.foo Il. est également une fonction Python générale, mais grâce au décorateur (@classmethod décorateur), elle devient un objet de méthode lié. Si vous souhaitez observer la fonction générale d'origine, vous ne pouvez la voir que dans Demo.bar.__func__. il est lié à la Demo classe, donc Demo.bar.__self__ fera référence à la Demo classe.

    2. Ainsi, lorsque Demo.bar est appelé (Demo.bar(1)), il appellera en fait Demo.bar.__func__ et utilisera Demo.bar.__self__ (en fait Demo lui-même) comme premier paramètre.

    S'il est montré en utilisant la classe que nous avons écrite, son exemple devient :

       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) 

    Code de test :

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

    Résultats des tests :

    === 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. En Python3, il existe deux types de fonctions en classe, l'une est un objet de fonction générale et l'autre est un objet de méthode lié

    2. La méthode instance est un objet méthode composé d'une fonction générale liée à une instance, et la classe mehtod est un objet méthode composé d'une fonction générale liée à une classe

    3. Lorsque la méthode
    4. liée est appelée, elle appelle en fait la fonction d'origine (enregistrée dans __func__), mais l'objet lié sera utilisé comme premier paramètre (enregistré dans __self__).


    Références :

    Différence entre les méthodes et les fonctions
    Différence pour créer un objet méthode d'instance en Python

    répondre
    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)
    

    répondre
    0
  • Annulerrépondre