Last active
March 11, 2016 08:36
-
-
Save minstrel271/77b3e3d412651d61b3cb to your computer and use it in GitHub Desktop.
This file contains 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 functools import lru_cache | |
class AttributeManager(object): | |
""" | |
A base class of attribute manager. | |
The name of the attribute are scanned and saved from the owner classes. | |
The value of each instance are saved as __name | |
>>> class Apple(object): | |
... favor = AttributeManager() | |
>>> apple = Apple() | |
>>> apple.favor = 'sweet' | |
>>> apple.favor | |
'sweet' | |
>>> apple.__favor | |
'sweet' | |
""" | |
def __init__(self, format='__{}'): | |
self.format = format | |
def __get__(self, instance, owner): | |
""" | |
When refered by an instance, return the managed attribute. | |
Otherwise, return itself. | |
""" | |
if instance is None: | |
return self | |
name = self.name(owner) | |
return getattr(instance, name) | |
def __set__(self, instance, value): | |
""" | |
Set the managed attribute as the value given | |
""" | |
name = self.name(type(instance)) | |
setattr(instance, name, value) | |
@lru_cache() | |
def name(self, owner): | |
""" | |
Scan the name of the managed attribute for the owner class. | |
The result are saved in lru_cache for future uses. | |
""" | |
for attr in dir(owner): | |
if getattr(owner, attr) is self: | |
return self.format.format(attr) | |
class const(object): | |
""" | |
A class constant manager where the managed content cannot be modified by instance. | |
For mutable attribute, a copy function can be provided for extra security. | |
>>> from copy import copy | |
>>> class Apple(object): | |
... favor = const('sweet') | |
... content = const(['water', 'sugar'], copy) | |
>>> apple = Apple() | |
>>> apple.favor | |
'sweet' | |
>>> apple.favor = 'sweet' | |
Traceback (most recent call last): | |
.... | |
RuntimeError: Modifing constant attribute | |
>>> apple.content[0] = 'oil' | |
>>> apple.content | |
['water', 'sugar'] | |
""" | |
def __init__(self, value, copy=None): | |
self.value = value | |
self.copy = copy | |
def __get__(self, instance, owner): | |
if self.copy is None: | |
return self.value | |
else: | |
return self.copy(self.value) | |
def __set__(self, instance, value): | |
raise RuntimeError('Modifing constant attribute') | |
class regulated(AttributeManager): | |
""" | |
A regulated attribute that check before setting its value. | |
Attributes: | |
regulate(self, value) (function): function that check/midify the value before saving | |
""" | |
def __init__(self, regulate, **kwargs): | |
super().__init__(**kwargs) | |
self.regulate = regulate | |
def __set__(self, instance, value): | |
super().__set__(instance, self.regulate(instance, value)) | |
if __name__ == '__main__': | |
import doctest | |
doctest.testmod() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment