python method-chaining

método de encadenamiento en python



method-chaining (3)

Es posible si solo utiliza funciones puras para que los métodos no modifiquen self.data directamente, sino que devuelvan la versión modificada. También tienes que devolver las instancias de Chainable .

Aquí hay un ejemplo que utiliza la recopilación de datos con listas:

import itertools try: import builtins except ImportError: import __builtin__ as builtins class Chainable(object): def __init__(self, data, method=None): self.data = data self.method = method def __getattr__(self, name): try: method = getattr(self.data, name) except AttributeError: try: method = getattr(builtins, name) except AttributeError: method = getattr(itertools, name) return Chainable(self.data, method) def __call__(self, *args, **kwargs): try: return Chainable(list(self.method(self.data, *args, **kwargs))) except TypeError: return Chainable(list(self.method(args[0], self.data, **kwargs)))

Úsalo así:

chainable_list = Chainable([3, 1, 2, 0]) (chainable_list .chain([11,8,6,7,9,4,5]) .sorted() .reversed() .ifilter(lambda x: x%2) .islice(3) .data) >> [11, 9, 7]

Tenga en cuenta que .chain refiere a itertools.chain y no a la chain OP.

(No debe confundirse con itertools.chain)

Estaba leyendo lo siguiente: http://en.wikipedia.org/wiki/Method_chaining

Mi pregunta es: ¿cuál es la mejor manera de implementar el encadenamiento de métodos en python?

Aquí está mi intento:

class chain(): def __init__(self, my_object): self.o = my_object def __getattr__(self, attr): x = getattr(self.o, attr) if hasattr(x, ''__call__''): method = x return lambda *args: self if method(*args) is None else method(*args) else: prop = x return prop list_ = chain([1, 2, 3, 0]) print list_.extend([9, 5]).sort().reverse() """ C:/Python27/python.exe C:/Users/Robert/PycharmProjects/contests/sof.py [9, 5, 3, 2, 1, 0] """

Un problema es si el method(*args) llamada method(*args) modifica self.o pero no devuelve None . (entonces debo devolver self o devolver el method(*args) devuelve).

¿Alguien tiene mejores formas de implementar el encadenamiento? Probablemente hay muchas maneras de hacerlo.

¿Debo suponer que un método siempre devuelve None así que siempre self.o devolver self.o ?


Hay una biblioteca de Pipe muy útil que puede ser la respuesta a su pregunta. Por ejemplo::

seq = fib() | take_while(lambda x: x < 1000000) / | where(lambda x: x % 2) / | select(lambda x: x * x) / | sum()


No habrá ninguna forma general de permitir que se encadene ningún método de ningún objeto, ya que no puede saber qué tipo de valor devuelve ese método y por qué sin saber cómo funciona ese método en particular. Los métodos pueden devolver None por cualquier razón; no siempre significa que el método haya modificado el objeto. Del mismo modo, los métodos que sí devuelven un valor aún podrían no devolver un valor que se pueda encadenar. No hay manera de encadenar un método como list.index : fakeList.index(1).sort() no puede tener muchas esperanzas de funcionar, porque todo el punto del index es que devuelve un número, y ese número significa algo, y no se puede ignorar solo para encadenar el objeto original.

Si solo estás jugando con los tipos incorporados de Python para encadenar ciertos métodos específicos (como ordenar y eliminar), es mejor que envuelvas esos métodos en particular explícitamente (anulando en tu clase de envoltorio), en lugar de intentar hacer un Mecanismo general con __getattr__ .