这两天有一个特殊需求,在一个Python class上实现一个method,可以被当作Class method调用,也可以被当作Instance的Method调用。看起来不是很Pythonic,一个函数有两个不同的行为,不过在特殊情况下确实很实用。
尝试对性能进行了一下优化,并没有用到太复杂的优化方法,所以只是相对性能可以接受。调用消耗大概是普通调用的一倍。
from functools import wraps
class hybridmethod(object):
"""
High performance hybrid function wrapper
"""
__slot__ = ['context', 'method', 'clsmethod']
def __init__(self, func):
self.clsmethod = self.method = wraps(func)(lambda *a, **kw: func(self.context, *a, **kw))
def classmethod(self, func):
"""
Function to call when calling with class
"""
self.clsmethod = wraps(func)(lambda *a, **kw: func(self.context, *a, **kw))
return self
def __get__(self, instance, cls):
if instance is None:
self.context = cls
return self.clsmethod
self.context = instance
return self.method
自己用到的场景:
class Model(object):
@hybridmethod
def from_dict(self, dict_):
"""
Inflate the instance with dict
"""
for k, v in dict_.items():
setattr(self, k, v)
return self
@from_dict.classmethod
def from_dict(cls, dict_):
"""
Inflate the instance with dict
"""
instance = cls()
for k, v in dict_.items():
setattr(instance, k, v)
return instance