2015-12-28 4 views
3

Considérez le code suivant:Vérifiez si l'objet est dans la liste (non « en valeur », mais par id)

Ainsi, in semble utiliser __eq__ pour déterminer si oui ou non quelque chose dans un récipient.

  1. Où peut-on trouver de la documentation sur ce comportement?
  2. Est-il possible de faire l'identité des objets in d'utilisation, si l'a in somelist a.k.a. objet a est somelist, et non un autre objet qui compare égal à a?
+0

liées: http://stackoverflow.com/q/29692140/674039 – wim

Répondre

6

Utilisez la any() function et une expression du générateur:

any(o is a for o in l) 

Le comportement de in est documentée dans le Common Sequence Operators section:

x in s
True si un élément de sest égal àx, sinon False

mine accent gras.

Si vous devez utiliser in, utilisez un objet emballage avec une méthode personnalisée __eq__ qui utilise is, ou construire votre propre conteneur où une coutume __contains__ method utilise is pour effectuer le test de chaque élément contenu.

L'enveloppe pourrait ressembler à ceci:

class IdentityWrapper(object): 
    def __init__(self, ob): 
     self.ob = ob 
    def __eq__(self, other): 
     return other is self.ob 

Démo:

>>> IdentityWrapper(a) in l 
False 
>>> IdentityWrapper(a) in (l + [a]) 
True 

Le conteneur pourrait simplement utiliser la même fonction any() décrit ci-dessus:

class IdentityList(list): 
    def __contains__(self, other): 
     return any(o is other for o in self) 

Démo:

>>> il = IdentityList(l) 
>>> a in il 
False 
>>> a in IdentityList(l + [a]) 
True 
+0

Ne pas utiliser '' in' __contains__'? – DeepSpace

+1

@DeepSpace: Oui, et si vous écrivez une séquence, vous êtes censé définir '__contains__' afin qu'il fasse ce que cette réponse décrit. – user2357112

+1

Je pense que 'in' utilise la méthode' __contains__' du conteneur, qui à son tour utilise '__eq__'. – Jasper

4

Si vous ne voulez pas changer le comportement A, vous pouvez préparer une fine enveloppe pour le conteneur usagé. Pour modifier le comportement de l'opérateur in, la méthode magique __contains__ doit être remplacée. Citations docs:

Appelées pour implémenter des opérateurs de test d'appartenance. Devrait retourner vrai si l'article est en soi, faux sinon. Pour les objets de mappage, cela doit prendre en compte les clés du mappage plutôt que les valeurs ou les paires d'éléments-clés .

Exemple de code:

class A(object): 
    def __init__(self, a): 
     self.a = a 

    def __eq__(self, other): 
     return self.a == other.a 


class IdentityList(list): 
    def __contains__(self, obj): 
     return any(o is obj for o in self) 

a = A(1) 
b = A(1) 
c = A(2) 
container = [b, c] 
identity_container = IdentityList(container) 
assert a in container # not desired output (described in question) 
assert a not in identity_container # desired output