class at_time:
actions = {}
def __init__(self, time_of_day):
self.time_of_day = time_of_day
def __call__(self, func):
self.actions.setdefault(func.__qualname__, {})[self.time_of_day] = func
return self
def __set_name__(self, owner, name):
self.name = name
for time_of_day, func in self.actions.pop(
'.'.join((owner.__qualname__, name))).items():
setattr(owner, f'_{name}_{time_of_day}', func)
def __get__(self, obj, objtype):
def wrapper(time_of_day):
try:
return getattr(obj, f'_{self.name}_{time_of_day}')()
except AttributeError:
raise ValueError(f'No {self.name} found in the {time_of_day} time')
return wrapper
class PersonalChef():
@at_time('morning')
def cook(self):
print("Cooking breakfast")
@at_time('evening')
def cook(self):
print("Cooking dinner")
class PersonalChefUK(PersonalChef):
@at_time('evening')
def cook(self):
print("Cooking supper")
PersonalChef().cook('morning')
PersonalChef().cook('evening')
PersonalChefUK().cook('morning')
PersonalChefUK().cook('evening')
Y2xhc3MgYXRfdGltZToKICAgIGFjdGlvbnMgPSB7fQoKICAgIGRlZiBfX2luaXRfXyhzZWxmLCB0aW1lX29mX2RheSk6CiAgICAgICAgc2VsZi50aW1lX29mX2RheSA9IHRpbWVfb2ZfZGF5CgogICAgZGVmIF9fY2FsbF9fKHNlbGYsIGZ1bmMpOgogICAgICAgIHNlbGYuYWN0aW9ucy5zZXRkZWZhdWx0KGZ1bmMuX19xdWFsbmFtZV9fLCB7fSlbc2VsZi50aW1lX29mX2RheV0gPSBmdW5jCiAgICAgICAgcmV0dXJuIHNlbGYKCiAgICBkZWYgX19zZXRfbmFtZV9fKHNlbGYsIG93bmVyLCBuYW1lKToKICAgICAgICBzZWxmLm5hbWUgPSBuYW1lCiAgICAgICAgZm9yIHRpbWVfb2ZfZGF5LCBmdW5jIGluIHNlbGYuYWN0aW9ucy5wb3AoCiAgICAgICAgICAgICAgICAnLicuam9pbigob3duZXIuX19xdWFsbmFtZV9fLCBuYW1lKSkpLml0ZW1zKCk6CiAgICAgICAgICAgIHNldGF0dHIob3duZXIsIGYnX3tuYW1lfV97dGltZV9vZl9kYXl9JywgZnVuYykKCiAgICBkZWYgX19nZXRfXyhzZWxmLCBvYmosIG9ianR5cGUpOgogICAgICAgIGRlZiB3cmFwcGVyKHRpbWVfb2ZfZGF5KToKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgcmV0dXJuIGdldGF0dHIob2JqLCBmJ197c2VsZi5uYW1lfV97dGltZV9vZl9kYXl9JykoKQogICAgICAgICAgICBleGNlcHQgQXR0cmlidXRlRXJyb3I6CiAgICAgICAgICAgICAgICByYWlzZSBWYWx1ZUVycm9yKGYnTm8ge3NlbGYubmFtZX0gZm91bmQgaW4gdGhlIHt0aW1lX29mX2RheX0gdGltZScpCiAgICAgICAgcmV0dXJuIHdyYXBwZXIKCmNsYXNzIFBlcnNvbmFsQ2hlZigpOgogICAgQGF0X3RpbWUoJ21vcm5pbmcnKQogICAgZGVmIGNvb2soc2VsZik6CiAgICAgICAgcHJpbnQoIkNvb2tpbmcgYnJlYWtmYXN0IikKCiAgICBAYXRfdGltZSgnZXZlbmluZycpCiAgICBkZWYgY29vayhzZWxmKToKICAgICAgICBwcmludCgiQ29va2luZyBkaW5uZXIiKQoKY2xhc3MgUGVyc29uYWxDaGVmVUsoUGVyc29uYWxDaGVmKToKICAgIEBhdF90aW1lKCdldmVuaW5nJykKICAgIGRlZiBjb29rKHNlbGYpOgogICAgICAgIHByaW50KCJDb29raW5nIHN1cHBlciIpCgpQZXJzb25hbENoZWYoKS5jb29rKCdtb3JuaW5nJykKUGVyc29uYWxDaGVmKCkuY29vaygnZXZlbmluZycpClBlcnNvbmFsQ2hlZlVLKCkuY29vaygnbW9ybmluZycpClBlcnNvbmFsQ2hlZlVLKCkuY29vaygnZXZlbmluZycp