Created
November 20, 2015 02:03
-
-
Save gitcrtn/952c2f2640a7d1ff89ee 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
# === base classes === | |
class OverrideProcessor(object): | |
def __init__(self,target_class): | |
self.method_names = tuple() # names tuple of override method | |
self.target_class = target_class # target class to override methods | |
self.reference_methods = {} # reference methods dict fot override target | |
self.setup() | |
self.do() | |
def setup(self): | |
pass # setup for before to override | |
def do(self): | |
for name,val in self.reference_methods.iteritems(): | |
if name in self.method_names: | |
setattr(self.target_class,name,self.method_creator(val)) | |
def method_creator(self,base_method): | |
return base_method | |
class AutoOverrideMeta(type): | |
def __new__(mcls, name, bases, attrs, override_processor): | |
cls = super(AutoOverrideMeta,mcls).__new__(AutoOverrideMeta,name,bases,attrs) | |
override_processor(cls) | |
return cls | |
class A(object): | |
def __init__(self,a=0,b=0,c=0): | |
if hasattr(a,'__getitem__'): | |
self.a, self.b, self.c = a | |
else: | |
self.a = a | |
self.b = b | |
self.c = c | |
def __getitem__(self,index): | |
value = (self.a,self.b,self.c) | |
try: | |
return value[index] | |
except: | |
raise IndexError('There are 3 values in this object, index should be 0, 1 or 2') | |
def foo(self): | |
return A(self.a+1, self.b+2, self.c+3) | |
def bar(self): | |
return A(self.a+4, self.b+5, self.c+6) | |
# === implemented classes === | |
class OverrideProcessorB(OverrideProcessor): | |
def __init__(self,target_class): | |
super(OverrideProcessorB,self).__init__(target_class) | |
def setup(self): | |
self.method_names = ('foo','bar') | |
self.reference_methods = self.target_class.__bases__[0].__dict__ | |
def method_creator(self,base_method): | |
def autocast_method(ins, *args, **kwargs): | |
ret = base_method(ins, *args, **kwargs) | |
casted_ret = self.target_class.__new__(self.target_class) | |
casted_ret.__init__(ret) | |
return casted_ret | |
return autocast_method | |
class AutoOverrideMetaB(AutoOverrideMeta): | |
def __new__(mcls, name, bases, attrs): | |
return super(AutoOverrideMetaB, mcls).__new__(AutoOverrideMetaB, name, bases, attrs, OverrideProcessorB) | |
class B(A): | |
__metaclass__ = AutoOverrideMetaB | |
# === test === | |
def test(): | |
b = B(1,2,3) | |
print B | |
print b.foo() | |
print b.bar() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment