Created
May 24, 2019 21:46
-
-
Save fre-sch/71a5c56363a30d6ebc53d6f991b8685b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import defaultdict | |
class ObservableAttr: | |
class _unset: pass | |
def __init__(self, default=_unset): | |
self.default = default | |
self.name = "unnamed" | |
def __set_name__(self, cls, name): | |
self.name = name | |
def __set__(self, inst, value): | |
try: | |
inst_attrs = inst.__observable_attrs | |
except AttributeError: | |
inst_attrs = inst.__observable_attrs = {} | |
inst_attrs[self.name] = value | |
try: | |
listeners = inst.__observable_attrs_listener | |
except AttributeError: | |
listeners = [] | |
for listener in listeners[self.name]: | |
listener(inst, self.name, value) | |
def __get__(self, inst, cls): | |
if inst is None: | |
return self | |
value = inst.__observable_attrs.get(self.name, self.default) | |
if value is ObservableAttr._unset: | |
raise AttributeError(self.name) | |
return value | |
def __repr__(self): | |
return f"ObservableAttr({self.name})" | |
@classmethod | |
def observe(cls, inst, attr, listener): | |
try: | |
listeners = inst.__observable_attrs_listener | |
except AttributeError: | |
listeners = inst.__observable_attrs_listener = defaultdict(list) | |
listeners[attr].append(listener) | |
class Model: | |
foo = ObservableAttr("default foo") | |
bar = ObservableAttr("default bar") | |
def listener(inst, attr, value): | |
print(f"{attr} on {inst} set to {value}") | |
model = Model() | |
ObservableAttr.observe(model, "foo", listener) | |
ObservableAttr.observe(model, "bar", listener) | |
model.foo = "new foo value" | |
model.bar = "new bar value" | |
print(f"model.foo {model.foo}") | |
print(f"model.bar {model.bar}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment