Estoy tratando de aprender el super() función en Python.

Pensé que tenía un asimiento de él hasta que me llegó a través de este ejemplo (2.6) y me encontré atrapado.

http://www.cafepy.com/article/python_attributes_and_methods/python_attributes_and_methods.html#super-with-classmethod-example

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 9, in do_something
    do_something = classmethod(do_something)
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
>>>

No era lo que yo esperaba cuando leí esta línea justo antes de la ejemplo:

Si estamos usando un método de clase, no tenemos una instancia para llamar a super con. Afortunadamente para nosotros, super funciona incluso con un tipo como el segundo argumento. — El tipo puede ser pasado directamente a los super como se muestra a continuación.

Que es exactamente lo que Python me dice que no es posible diciendo que do_something() debe ser llamado con una instancia de B.

InformationsquelleAutor dezza | 2009-11-29

5 Comentarios

  1. 80

    A veces, los textos tienen que ser leer más para que el sabor de la idea, más que por los detalles. Este es uno de esos casos.

    En el página enlazada, Ejemplos 2.5, 2.6 y 2.7, todas deben usar un método, do_your_stuff. (Que es, do_something debe ser cambiado a do_your_stuff.)

    Además, como Ned Deily señaló, A.do_your_stuff tiene que ser un método de clase.

    class A(object):
        @classmethod
        def do_your_stuff(cls):
            print 'This is A'
    
    class B(A):
        @classmethod
        def do_your_stuff(cls):
            super(B, cls).do_your_stuff()
    
    B.do_your_stuff()

    super(B, cls).do_your_stuff
    devuelve un obligado método (ver nota de pie de página 2). Desde cls se pasa como segundo argumento a super(), es cls que se presenta vinculado a la devuelve el método. En otras palabras, cls se pasa como primer argumento para el método do_your_stuff() de clase A.

    A reiterar: super(B, cls).do_your_stuff() causas A‘s do_your_stuff método
    llama con cls pasado como primer argumento. En orden para que funcione, A‘s
    do_your_stuff tiene que ser un método de clase. La página vinculada no mencionar que,
    pero que es definitivamente el caso.

    PS. do_something = classmethod(do_something) es la manera antigua de hacer un classmethod.
    El nuevo(er) es la utilización de la @classmethod decorador.


    Nota que super(B, cls) no pueden ser sustituidos por super(cls, cls). Si lo hace, podría provocar bucles infinitos. Por ejemplo,

    class A(object):
        @classmethod
        def do_your_stuff(cls):
            print('This is A')
    
    class B(A):
        @classmethod
        def do_your_stuff(cls):
            print('This is B')
            # super(B, cls).do_your_stuff()  # CORRECT
            super(cls, cls).do_your_stuff()  # WRONG
    
    class C(B):
        @classmethod
        def do_your_stuff(cls):
            print('This is C')
            # super(C, cls).do_your_stuff()  # CORRECT
            super(cls, cls).do_your_stuff()  # WRONG
    
    C.do_your_stuff()

    elevará RuntimeError: maximum recursion depth exceeded while calling a Python object.

    Si cls es C, entonces super(cls, cls) búsquedas C.mro() para la clase que viene después de C.

    In [161]: C.mro()
    Out[161]: [__main__.C, __main__.B, __main__.A, object]

    Ya que la clase es B, cuando cls es C, super(cls, cls).do_your_stuff() siempre llamadas B.do_your_stuff. Desde super(cls, cls).do_your_stuff() se llama dentro de B.do_your_stuff, al final llama a B.do_your_stuff en un bucle infinito.

    En Python3, el 0-argumento la forma de super se ha agregado para super(B, cls) podría ser reemplazado por super(), y Python3 se figura fuera de contexto que super() en la definición de class B debe ser equivalente a super(B, cls).

    Pero en ningún caso es super(cls, cls) (o por razones similares, super(type(self), self)) siempre correcta.

    • Hay dificultades en el uso de super(cls cls)?
    • cls) es casi ciertamente un error. He editado el post de arriba a explicar por qué.
  2. 14

    En Python 3, puede omitir la especificación de argumentos para super,

    class A:
        @classmethod
        def f(cls):
            return "A's f was called."
    
    class B(A):
        @classmethod
        def f(cls):
            return super().f()
    
    assert B.f() == "A's f was called."
    • Esta respuesta podría ser movido a otra pregunta, si esta pregunta en particular es el de trabajar con Python 2 específicamente (es difícil decir desde el sitio web vinculado, CafePy, ya no está disponible).
    • No es trabajo para mí en un proyecto de la mina. Se está dando RuntimeError: super(): no arguments
  3. 3

    He actualizado el artículo para que sea un poco más claro: Python Atributos y Métodos de # Super

    Su ejemplo de uso de classmethod de arriba muestra lo que es un método de clase se – pasa de la misma clase en lugar de la instancia como el primer parámetro. Pero usted ni siquiera necesita una instancia para llamar al método, por ejemplo:

    >>> class A(object):
    ...     @classmethod
    ...     def foo(cls):
    ...         print cls
    ... 
    >>> A.foo() # note this is called directly on the class
    <class '__main__.A'>
  4. 2

    El ejemplo de la página web parece funcionar como publicado. ¿Crear un do_something método de la superclase, como bien, pero no se hará en un classmethod? Algo parecido a esto le dará un error:

    >>> class A(object):
    ...     def do_something(cls):
    ...         print cls
    ... #   do_something = classmethod(do_something)
    ... 
    >>> class B(A):
    ...     def do_something(cls):
    ...         super(B, cls).do_something()
    ...     do_something = classmethod(do_something)
    ... 
    >>> B().do_something()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 3, in do_something
    TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
    • No, mi clase se parece a esto: clase a(object): def do_your_stuff(self): print «este es Un» Es necesario tener «clase» como te lo envió? (con do_something = classmethod(do_something)) ? Me siento como el documento no dice nada acerca de esto ..
    • El punto entero de la super llamada en la B do_something método es llamar a un método con ese nombre en una de sus superclases. Si no hay una en Una (o en el Objeto), la B().do_something() llamada falla con super object has no attribute do_something. ~unutbu señala con razón que el ejemplo en el documento es defectuoso.
  5. 0

    Creo que he entendido el punto ahora, gracias a este hermoso sitio y encantadora de la comunidad.

    Si no te importa por favor me corrija si estoy equivocado en classmethods (que ahora estoy tratando de comprender plenamente):

    
    # EXAMPLE #1
    >>> class A(object):
    ...     def foo(cls):
    ...             print cls
    ...     foo = classmethod(foo)
    ... 
    >>> a = A()
    >>> a.foo()
    # THIS IS THE CLASS ITSELF (__class__)
    class '__main__.A'
    
    # EXAMPLE #2
    # SAME AS ABOVE (With new @decorator)
    >>> class A(object):
    ...     @classmethod
    ...     def foo(cls):
    ...             print cls
    ... 
    >>> a = A()
    >>> a.foo()
    class '__main__.A'
    
    # EXAMPLE #3
    >>> class B(object):
    ...     def foo(self):
    ...             print self
    ... 
    >>> b = B()
    >>> b.foo()
    # THIS IS THE INSTANCE WITH ADDRESS (self)
    __main__.B object at 0xb747a8ec
    >>>

    Espero que esta ilustración muestra ..

Dejar respuesta

Please enter your comment!
Please enter your name here