Reputation: 51
I'm working through the Building Skills in Object Oriented Design in python and am on the wheel section for roulette. We've created a "Bin" class as an extended class from frozenset which will represent each of the positions on the roulette wheel. We then create a tuple of 38 empty "Bins", and now have to create class methods to be able to add odds/outcomes to the Bins.
My problem is that I've not been able to create a method to modify the Bin in position without the result not reverting to the frozenset class.
My desired output is to have:
class Bin(frozenset):
def add(self, other):
....do union of Bin class....
one = Bin(1, 2, 3)
two = Bin(4, 5)
one.add(two)
print(one)
>>> Bin(1, 2, 3, 4, 5)
Stuff I've tried
Extending the frozenset class with no methods defined/overridden
class Bin(frozenset):
pass
one = Bin([1,2,3])
two = Bin([4,5,6])
print(one|two)
print(type(one|two))
Which returns
frozenset({1, 2, 3, 4, 5, 6})
<class 'frozenset'>
I would have expected that by extending the class and using one of the extended methods that the output would remain as the "Bin" class.
I've also tried overriding the __ ror__ & union methods with the same result. I've tried to create a method which to brute force return the desired output. This however does not allow me to change the tuple of Bins as it doesn't operate in place
class Bin(frozenset):
def add(self, other):
self = Bin(self|other)
return self
one = Bin([1,2,3])
two = Bin([4,5,6])
one.add(two)
print(one)
Which returns
Bin({1, 2, 3})
Any insight into where in falling down in my thinking would and/or recommendations of stuff to read for further insight would be great.
Upvotes: 1
Views: 97
Reputation: 81684
frozenset.__or__
(which is called by the default implementation of Bin.__or__
when 'triggered' by one | two
) has no idea that frozenset
was subclassed by Bin
, and that it should return a Bin
instance.
You should implement Bin.__or__
and force it to return a Bin
instance:
class Bin(frozenset):
def __or__(self, other):
# be wary of infinite recursion if using | incorrectly here,
# better to use the underlying __or__
return Bin(super().__or__(other))
one = Bin([1, 2, 3])
two = Bin([4, 5, 6])
print(one | two)
print(type(one | two))
Outputs
Bin({1, 2, 3, 4, 5, 6})
<class '__main__.Bin'>
Upvotes: 1
Reputation: 3866
You need to do something like this (to avoid infinite recursion):
class Bin(frozenset):
def __or__(self, other):
return Bin(frozenset(self) | other)
Upvotes: 0