总所周知,Python
里有一个非常出名的魔术方法是__str__
,它常用于对于一个Python
对象的字符转化,比如:
class Foo(object):
def __init__(self):
pass
def __str__(self):
return 'Foo Class'
foo = Foo()
str(foo)
# 'Foo Class'
那么,如果要对Python
中的一个函数实现类似的效果,应该怎么做呢?
按照魔术方法本身定位而言,dunder方法一般只是针对于对象,而不是函数。但好在Python
是动态语言,支持duck type特性,从这个思路出发,可以找到解决的办法。
def with_str (str_func):
def wrapper (f):
class FuncType:
def __call__ (self, *args, **kwargs):
return f(*args, **kwargs)
def __str__ (self):
return str_func()
return functools.wraps(f)(FuncType())
return wrapper
def foo_str():
return 'This is __str__ for foo!'
@with_str(foo_str)
def foo():
print('Hello world!')
foo
# 'Hello world'
str(foo)
# 'This is __str__ for foo!'
简单来说,实现的思路是将原有函数转化成一个对象,当调用这个对象的时候,触发__call__
直接调用原有函数,为这个对象绑定__str__
的方法。从实现效果来看,就好像是函数具备了__str__
的魔术方法。这也就是动态语言的优越性,名副其实的duck type。原文地址
另外再提一个实际开发当中经常遇到的问题。在面对web开发的过程当中。经常需要将数据dumps成json返回给response。不巧的是,Python
中的对象与json中的对象并非一一对应的关系,即便把范围缩小到Python
中的内置对象,也有常见的decimal,datetime等对象无法正确的dumps到json中。
这时的主要思路是在json.dumps是检测特殊类型并单独处理。
一个简单的实现是:
import json
import decimal
import datetime
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return float(obj)
if isinstance(obj, datetime.datetime):
return obj.strftime( '%Y-%m-%d %H:%M:%S' )
return super(MyEncoder, self).default(obj)
json.dumps(data, cls=MyEncoder)
上面重写了json.dumps中的encoder部分,也可以重写一个to_json的方法来对特殊类型进行特殊处理。
前段时间在一个微信公众号的一篇文章中偶然看见了一种实现方法:
import json
import decimal
import datetime
from functools import singledispatch
@singledispatch
def myEncoder(obj):
raise TypeError('Must be impelement!')
@myEncoder.register(datetime.datetime)
def _(obj):
return obj.strftime( '%Y-%m-%d %H:%M:%S' )
@myEncoder.register(decimal.Decimal)
def _(obj):
return float(obj)
class MyEncoder(json.JSONEncoder):
def default(self, obj):
try:
myEncoder(obj)
except TypeError:
return super(MyEncoder, self).default(obj)
json.dumps(data, cls=MyEncoder)
这里使用了Python3.4
中新增的singledispatch特性来解决这种单泛型的问题,当有新的特殊类型时,仅需要新增注册方法即可。关于singledispatch的更对信息:点我
参考链接:
https://stackoverflow.com/questions/47452513/how-do-you-implement-str-for-a-function
https://mp.weixin.qq.com/s/icNu9hO80opzq4CxuF4unQ
侵删
网友评论