美文网首页
Python中给函数添加属性

Python中给函数添加属性

作者: MontyOak | 来源:发表于2017-11-28 22:52 被阅读338次

总所周知,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
侵删

相关文章

  • Python中给函数添加属性

    总所周知,Python里有一个非常出名的魔术方法是__str__,它常用于对于一个Python对象的字符转化,比如...

  • 构造函数

    构造函数是干什么用的? 在javascript中,构造函数是给对象添加属性,初始化属性作用的。 对象创建的过程 首...

  • 详解Javascript函数中with

    Javascript函数中with,with函数方便用来引用某个对象中已有的属性,但是不能用来给对象添加属性,要给...

  • [ES] 函数的name属性

    一、背景 ECMAScript使用SetFunctionName,给函数添加name属性。 SetFunction...

  • Python中给函数添加元信息

    问题背景 我们写好一个自定义函数之后,要告诉其他人其他人怎么用这个函数,可以利用->为函数添加一些元信息,比如这个...

  • 理解Python函数装饰器

    搬运自本人博客: sikaixing.com Python中的函数装饰器是一种能在不修改函数的前提下给函数添加额外...

  • Python学习之路

    一、Python 中类的属性分为实例属性和类属性,属性就是附在对象后可被引用的函数或者数据。通常我们将类中的函数又...

  • JS Tips

    遍历对象的所有属性 添加属性 给普通的 JS 对象添加属性: 但是对于 Mongodb 中的对象,不可直接添加属性...

  • 函数作为对象

    给函数添加属性应用:1.在集合中存储函数可以帮助我们轻易地管理相关函数。例如,某些特定情况下必须调用回调函数。2....

  • vs2017开发ActiveX(主讲OCX)(十一)、类向导中M

    本文我们就来说说类向导中MFC ActiveX添加方法、添加函数、添加变量、添加事件、添加属性、添加方法的区别。这...

网友评论

      本文标题:Python中给函数添加属性

      本文链接:https://www.haomeiwen.com/subject/dbcybxtx.html