Skip to content

Instantly share code, notes, and snippets.

@gitcrtn
Created November 20, 2015 02:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gitcrtn/952c2f2640a7d1ff89ee to your computer and use it in GitHub Desktop.
Save gitcrtn/952c2f2640a7d1ff89ee to your computer and use it in GitHub Desktop.
メタクラスによる自動オーバーライド(自動キャスト)
# === 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