python callable method-chaining

subplot title python



Método básico de encadenamiento (2)

El encadenamiento de métodos es simplemente poder agregar .second_func() a lo que .first_func() . Se implementa con bastante facilidad asegurándose de que todos los métodos elegibles vuelvan a self . (Tenga en cuenta que esto no tiene nada que ver con __call()__ ).

class foo(): def __init__(self, kind=None): self.kind = kind def my_print(self): print (self.kind) return self def line(self): self.kind = ''line'' return self def bar(self): self.kind=''bar'' return self

Puedes usar los objetos foo de una manera no encadenada ignorando sus valores devueltos:

a = foo() a.line() a.my_print() a.bar() a.my_print() assert a.kind == ''bar''

O, como cada función ahora devuelve el objeto en sí, puede operar directamente sobre el valor devuelto. Puedes usar el método de encadenamiento con este código equivalente:

b = foo() b.line().my_print().bar().my_print() assert b.kind == ''bar''

O incluso:

c = foo().line().my_print().bar().my_print() assert c.kind == ''bar''

La cuestión de deshacerse de la () sintaxis de llamada es un concepto completamente separado del encadenamiento de métodos. Si quieres propiedades de cadena y tienes esas propiedades mutando su objeto, usa el decorador @property . (Pero mutar objetos a través de una propiedad parece peligroso. Es mejor usar un método y nombrarlo con un verbo: .set_line() lugar de .line , por ejemplo).

class foo(): def __init__(self, kind=None): self.kind = kind def my_print(self): print (self.kind) return self @property def line(self): self.kind = ''line'' return self @property def bar(self): self.kind=''bar'' return self a = foo() a.line a.my_print() a.bar a.my_print() assert a.kind == ''bar'' b = foo() b.line.my_print().bar.my_print() assert b.kind == ''bar'' c = foo().line.my_print().bar.my_print() assert c.kind == ''bar''

Encontré este método de encadenamiento en Python , pero incluso con eso no pude entender el método de encadenamiento en Python.

Aquí los objetivos son dos: resolver el problema de codificación y comprender el encadenamiento de métodos (dado que todavía no estoy 100% seguro con callables).

Hasta la definición del problema.

Quiero una clase que tenga dos métodos: uno establece un parámetro del objeto = ''línea'' y el otro sobrescribe en ''barra''.

Esto es lo que tengo hasta ahora:

class foo(): def __init__(self, kind=None): self.kind = kind def __call__(self, kind=None): return foo(kind=kind) def my_print(self): print (self.kind) def line(self): return self(kind=''line'') def bar(self): return self(kind=''bar'')

Lamentablemente, con este código puedo lograr mi objetivo haciendo esto.

a = foo() a.bar().line().bar().bar().line().my_print()

Pero me gustaría obtener el mismo resultado escribiendo este código

a = foo() a.bar.line.bar.bar.line.my_print()

¿Cómo logro esto? Supongo que algo está mal en cómo __call__ método __call__ . Gracias de antemano por tu ayuda.


Utilizar propiedades (descriptores).

class foo: def __init__(self, kind=None): self.kind = kind def __call__(self, kind=None): return foo(kind=kind) def my_print(self): print (self.kind) @property def line(self): return self(kind=''line'') @property def bar(self): return self(kind=''bar'')

Tenga en cuenta, sin embargo, que no sobrescribe nada, la modificación no funciona en el lugar (lo que podría decirse que es bueno, por cierto). De todos modos, esto no parece una buena opción de diseño para la mayoría de los casos del mundo real, porque en algún momento sus métodos requerirán argumentos.