editar: cambié el título de complement a converse después de la discusión a continuación.
En el módulo operator , las funciones binarias que comparan objetos toman dos parámetros. Pero la función contains los ha intercambiado.
Uso una lista de operadores, por ejemplo, operator.lt , operator.ge .
Toman 2 argumentos, a y b .
Puedo decir operator.lt(a, b) y me dirá si a es menor que b .
Pero con operator.contains , quiero saber si b contiene a así que tengo que intercambiar los argumentos.
Esto es una molestia porque quiero una interfaz uniforme, por lo que puedo tener una lista de operaciones definida por el usuario para usar (estoy implementando algo como Django QL).
Sé que podría crear una función auxiliar que intercambie los argumentos:
def is_contained_by(a, b): return operator.contains(b, a)¿Hay una forma "estándar" de hacerlo?
Alternativamente, puedo implementar todo al revés, excepto contains . Asigne lt a ge , etc., pero eso se vuelve realmente confuso.
Si alguno de ellos publica una respuesta, debe aceptarla, pero entre los usuarios @chepner y @khelwood, ellos le dieron la mayor parte de la respuesta.
El complemento de operator.contains sería algo así como operator.does_not_contain , por lo que no es exactamente lo que está buscando. Aunque creo que un 'reflejo' tampoco es exactamente lo que buscas, ya que sería esencialmente su inverso, si estuviera definido.
En cualquier caso, como señala @chepner, contains no está al revés. Simplemente no es lo mismo que in , in estaría contenido como lo is_contained_by .
Considere que a in b no sería a contains b , sino que b contains a , por lo que la firma de operator.contains tiene sentido. Sigue la convención de que la operación infija indicada de la función sea su nombre. Es decir (a < b) == operator.lt(a, b) y b contains a == operator.contains(b, a) == (a in b) . (en un mundo donde contains sería un operador infijo existente)
Aunque no lo recomendaría, porque puede causar confusión con otras personas que lean su código y hagan suposiciones incorrectas, podría hacer algo como:
operator.in_ = lambda a, b: b.__contains__(a) # or operator.in_ = lambda a, b: operator.contains(b, a) Eso le daría un operator.in_ que funciona como espera (y evita la palabra clave in ), pero a costa de un poco de sobrecarga y posible confusión. Recomiendo trabajar con operator.contains en su lugar.
Si su objetivo es la uniformidad, podemos ir mucho más general que una función de ayuda que funciona específicamente para contains .
def flip(f): return lambda y, x: f(x, y) Ahora flip(operator.gt) se comportará (en cualquier clase) como operator.lt , y flip(operator.contains) es la función que desea.