Wednesday, 15 August 2012

python - Overloading __eq__ to return custom objects -



python - Overloading __eq__ to return custom objects -

i writing dsl in python , want overload operators able write expressions of dsl. example, want write var("a") + var("b") , equivalent representation of add(var("a"), var("b")). this, overloaded __add__ method, , works fine one.

nevertheless, seek overload __eq__ method accomplish similar: want write var("a") == var("b") , equivalent representation of eq(var("a"), var("b")). overloading __eq__ method, returning instance of eq, achieved goal. when overloading __eq__ method, interferes behaviour of standard python, such var("b") in [var("a")] returning true.

is there way accomplish goal, is, beingness able write var("a") == var("b") , eq(var("a"), var("b")), still beingness able write if var("a") == var("b"): blablabla or putting expressions in built-in containers, etc.?

edit

i tried implement __bool__ method of eq class, , seems work (see next code). there i'm missing or viable solution?

class expr: def __add__(self, other): homecoming add(self, other) def __eq__(self, other): homecoming eq(self, other) def __repr__(self): homecoming str(self) def __add__(self, other): homecoming add(self, other) def __ne__(self, other): homecoming neq(self, other) class var(expr): def __init__(self, name): self.name = name def __str__(self): homecoming "var(" + str(self.name) + ")" def equals(self, other): if type(self) type(other): homecoming self.name == other.name else: homecoming false def __hash__(self): homecoming 17 + 23 * hash(self.name) class add(expr): def __init__(self, left, right): self.left = left self.right = right def __str__(self): homecoming "add(" + str(self.left) + ", " + str(self.right) + ")" def equals(self, other): if type(self) type(other): homecoming ( ( self.left.equals(other.left) , self.right.equals(other.right) ) or ( self.left.equals(other.right) , self.right.equals(other.left) ) ) else: homecoming false def __hash__(self): homecoming (17 + 23 * hash("+") + 23 * 23 * hash(self.left) + 23 * 23 * hash(self.right)) class eq(expr): def __init__(self, left, right): self.left = left self.right = right def __str__(self): homecoming "eq(" + str(self.left) + ", " + str(self.right) + ")" def equals(self, other): if type(self) type(other): homecoming ( ( self.left.equals(other.left) , self.right.equals(other.right) ) or ( self.left.equals(other.right) , self.right.equals(other.left) ) ) else: homecoming false def __bool__(self): homecoming self.left.equals(self.right) def __hash__(self): homecoming (17 + 23 * hash("==") + 23 * 23 * hash(self.left) + 23 * 23 * hash(self.right)) class neq(expr): def __init__(self, left, right): self.left = left self.right = right def __str__(self): homecoming "neq(" + str(self.left) + ", " + str(self.right) + ")" def equals(self, other): if type(self) type(other): homecoming ( ( not self.left.equals(other.left) or not self.right.equals(other.right) ) , ( not self.left.equals(other.right) or not self.right.equals(other.left) ) ) else: homecoming false def __bool__(self): homecoming not self.left.equals(self.right) def __hash__(self): homecoming (17 + 23 * hash("!=") + 23 * 23 * hash(self.left) + 23 * 23 * hash(self.right)) = var("a") aa = var("a") b = var("b") c = var("c") print("a + b", "=>", + b) # + b => add(var(a), var(b)) print("a == b", "=>", == b) # == b => eq(var(a), var(b)) print("a != b", "=>", != b) # != b => neq(var(a), var(b)) print("a if == b else b", "=>", if == b else b) # if == b else b => var(b) print("a if == aa else b", "=>", if == aa else b) # if == aa else b => var(a) l = [a, a+b] print("l", "=>", l) # l => [var(a), add(var(a), var(b))] print("b in l", "=>", b in l) # b in l => false print("a in l", "=>", in l) # in l => true print("aa in l", "=>", aa in l) # aa in l => true print("a+b in l", "=>", a+b in l) # a+b in l => true print("b+a in l", "=>", b+a in l) # b+a in l => true print("a+c in l", "=>", a+c in l) # a+c in l => false if == b: print("a == b true") else: print("a == b false") # == b false if == aa: print("a == aa true") # == aa true else: print("a == aa false") if != b: print("a != b true") # != b true else: print("a != b false") if != aa: print("a != aa true") else: print("a != aa false") # != aa false if == b or == aa: print("a == b or == aa true") # == b or == aa true else: print("a == b or == aa false") if == aa , == b: print("a == aa , == b true") else: print("a == aa , == b false") # == aa , == b false if not == aa: print("not == aa true") else: print("not == aa false") # not == aa false if not == b: print("not == b true") # not == b true else: print("not == b false") if == 3: print("a == 3 true") else: print("a == 3 false") # == 3 false if != 3: print("a != 3 true") # != 3 true else: print("a != 3 false") if 3 == a: print("3 == true") else: print("3 == false") # 3 == false if 3 != a: print("3 != true") # 3 != true else: print("3 != false") if == 'a': print("a == 'a' true") else: print("a == 'a' false") # == 'a' false if != 'a': print("a != 'a' true") # != 'a' true else: print("a != 'a' false") if 'a' == a: print("'a' == true") else: print("'a' == false") # 'a' == false if 'a' != a: print("'a' != true") # 'a' != true else: print("'a' != false") s = {a} print("s", "=>", s) # s => {var(a)} print("a in s", "=>", in s) # in s => true print("b in s", "=>", b in s) # b in s => false print("aa in s", "=>", aa in s) # aa in s => true d = {a: 1, b: 2} print("d", "=>", d) # d => {var(b): 2, var(a): 1} print("d[a]", "=>", d[a]) # d[a] => 1 print("d[b]", "=>", d[b]) # d[b] => 2 print("c in d", "=>", c in d) # c in d => false print("aa in d", "=>", aa in d) # aa in d => true print("d[aa]", "=>", d[aa]) # d[aa] => 1

no, can not. you'll have pick 1 behaviour or other. context in .__eq__() method beingness used not (reliably) detectable.

if need both, you'll need utilize different operator, or method, represent dsl behaviour.

python python-3.x operator-overloading

No comments:

Post a Comment