Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Passage dans la fonction __contains__

+1 vote

J'essaye d'enregistrer des opérations de comparaisons dans un object pour un traitement en masse sur des instances.

import operator

class QueryOp(object):
    """
        Enregistre l’opération de requête 
    """
    def __init__(self, op, left, right):
        self.op = op
        self.left = left
        self.right = right

    def __call__(self, instance):
        return self.op(getattr(instance, self.left.name), self.right)

class Descriptor(object):
    def __init__(self):
        self.name = "attr" # normalement traiter par ma classe Model

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        instance.__dict__[self.name] = value

    def __eq__(self, other):
        print self.name, "==", other
        return QueryOp(operator.eq, self, other)

    def __contains__(self, other):
        print other, "in", self.name      # je passe portant ici
        return QueryOp(operator.contains, self,  other)

class Klass(object):
    attr = Descriptor()


k = Klass()
k.attr = "une_valeur"

def evaluate_query(instance, query):
    assert isinstance(query, QueryOp)
    return query(instance)



print evaluate_query(k, Klass.attr == "une_valeur") # Nickel
print evaluate_query(k, "une" in Klass.attr) # Failed

Tout ce passe bien pour l'égalité ( eq) et pour les autres fonctions de comparaisons.
En revanche, je plante sur l'assert avec l’opérateur in :
- je rentre bien dans contains
- je crée bien mon object
mais je retourne systématiquement un boolean, sans pouvoir récupérer mon object

est ce qu'il y a un moyen de récupérer l'object ?
faut-il passer par une autre fonction ?
pas possible ??

demandé 27-Jan-2015 par Kermit (210 points)

__contains__ est une magic method qui renverra tjrs un booleen quoi qu'il arrive. J'ai pas bien saisi ta demarche, cependant:

print(type("une" in k.attr)) # <-- str in str: renvoie bool 
print(type(QueryOp)) # <-- renvoie type  

Pour mon objectif d'utilisation, je cherche à sauvegarder les informations de mon filtrage.
Et non a tester mon instance dans l'immédiat, cela se fera ailleurs.

Dans l'appel de ma fonction evaluate_query,
je ne compare pas l'attribut attr de l'instance k,
mais le descripteur attr de la classe Klass

1 Réponse

+2 votes
 
Meilleure réponse

__contain__ retourne toujours un boolean, il n'y a pas moyen de lui faire retourner un objet malheureusement.

répondu 27-Jan-2015 par Sam (5,000 points)
sélectionné 27-Jan-2015 par Kermit

Bouhouhouu, recommence, la réponse ne me plait pas.

Merci pour le lien, je n'arrivais pas à trouver l'information de manière explicite.

Je vais opter pour la syntaxe de peewee qui utilise le << à la place du in
http://docs.peewee-orm.com/en/latest/peewee/querying.html#filtering-records

...