Instantly share code, notes, and snippets.

Embed
What would you like to do?
import operator
import collections
class Rule(object):
def __init__(self, logic, left=None, right=None, op=None, inv=False):
self.logic = logic
self.left = left
self.right = right
self.op = op
self.inv = inv
def __call__(self, *given):
if self.logic is not None:
return self._run(*given)
elif None not in (self.left, self.right, self.op):
return self.op(
self.left(*given) ,
self.right(*given)) ^ self.inv
def _run(self, *given):
return self.logic(*given) ^ self.inv
def __or__(self, other):
return Rule(logic=None, left=self, right=other, op=operator.or_)
def __and__(self, other):
return Rule(logic=None, left=self, right=other, op=operator.and_)
def __invert__(self):
return Rule(logic=self.logic, left=self.left, right=self.right,
op=self.op, inv=True)
# Rules
is_an_adult = Rule(lambda x: x.age > 18)
has_any_degree = Rule(lambda x: len(x.degrees) > 0)
still_in_school = Rule(lambda x: len(x.degrees) == 0)
lives_in_lebanon = Rule(lambda x: x.country == 'Lebanon')
lives_in_egypt = Rule(lambda x: x.country == 'Egypt')
lives_in_france = Rule(lambda x: x.country == 'France')
has_BS = Rule(lambda x: 'BS' in x.degrees)
has_MS = Rule(lambda x: 'MS' in x.degrees)
has_BE = Rule(lambda x: 'BE' in x.degrees)
# Rule Composition
is_loser = is_an_adult & still_in_school
is_doomed = is_an_adult & has_any_degree & lives_in_lebanon
is_middle_eastern = lives_in_lebanon | lives_in_egypt
fits_position_requirements = has_BE | (has_BS & has_MS)
is_school_boy = ~is_an_adult & still_in_school
is_possible_candidate = fits_position_requirements & ~is_doomed
# Sample Data
Person = collections.namedtuple('Person', ['name','age','country','degrees'])
joe = Person(name='joe', age=17, country='France', degrees=['BE'])
omar = Person(name='omar', age=34, country='Lebanon', degrees=['BS'])
sam = Person(name='sam', age=24, country='Finland', degrees=['BS', 'MS'])
jaafar = Person(name='dave', age=23, country='Egypt', degrees=[])
dany = Person(name='dany', age=12, country='France', degrees=[])
# Checks
assert lives_in_france(joe)
assert is_loser(jaafar)
assert is_middle_eastern(jaafar)
assert is_doomed(omar)
assert fits_position_requirements(joe)
assert fits_position_requirements(sam)
assert not fits_position_requirements(omar)
assert is_school_boy(dany)
assert not is_possible_candidate(omar)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment