Pregunta Python: las funciones devueltas por itemgetter () no funcionan como se esperaba en las clases


los operator.itemgetter () la función funciona así:

>>> import operator
>>> getseconditem = operator.itemgetter(1)
>>> ls = ['a', 'b', 'c', 'd']
>>> getseconditem(ls) 
'b'

EDITAR He añadido esta parte para resaltar la inconsistencia

>>> def myitemgetter(item):
...     def g(obj):
...         return obj[item]
...     return g
>>> mygetseconditem = myitemgetter(1)

Ahora, tengo esta clase

>>> class Items(object):
...     second = getseconditem
...     mysecond = mygetseconditem
...
...     def __init__(self, *items):
...         self.items = items
...
...     def __getitem__(self, i):
...         return self.items[i]

Accediendo al segundo elemento con sus trabajos de índice

>>> obj = Items('a', 'b', 'c', 'd')
>>> obj[1] 
>>> 'b'

Y también lo hace accediendo a través del mysecond método

>>> obj.mysecond()
'b'

Pero por alguna razón, usando el second() método plantea una excepción

>>> obj.second()
TypeError: itemgetter expected 1 arguments, got 0

¿Lo que da?


8
2018-01-18 07:03


origen


Respuestas:


obj.second es la función getseconditem. Una función que espera que un argumento funcione. Desde que llamaste obj.second sin ningún argumento, se genera el error que usted dio. Para resolverlo puedes hacer obj.second(obj.items) o definir second diferentemente:

class Items(object):
    def __init__(self, *items):
        self.items = items

    def __getitem__(self, i):
        return self.items[i]

    def second(self):
        return getseconditem(self.items)

Editar

Está claro lo que quieres decir ahora después de editar tu pregunta. Creo que lo que está pasando aquí es eso porque getseconditem no es un usuario definido función no se transforma en un método al acceder obj.second. Simplemente se mantiene como una función. Lo siguiente se puede encontrar en docs:

Tenga en cuenta que la transformación de objeto de función a (sin consolidar o   obligado) el objeto de método ocurre cada vez que se recupera el atributo de   la clase o instancia. En algunos casos, una optimización fructífera es   asigna el atributo a una variable local y llama a esa variable local.    También tenga en cuenta que esta transformación solo ocurre para el usuario definido   funciones; otros objetos invocables (y todos los objetos no llamables) son   recuperado sin transformación.


7
2018-01-18 07:06



el problema parece estar en lo siguiente:

>>> print (getseconditem, mygetseconditem)
(<operator.itemgetter object at 0x01EE5BD0>, <function g at 0x00504DB0>)

En otras palabras, una función puede vincularse, pero una llamada no puede.


1
2018-01-18 07:18