如何使用Python中的装饰器创建具有实例化时间变量的新函数/方法

在这里插入图片描述

1、问题背景

在Python中,我们可以使用装饰器来修改函数或方法的行为,但当装饰器需要使用一个在实例化时创建的对象时,事情就会变得复杂。

例如,我们想要创建一个装饰器,可以创建一个新的函数/方法来使用对象obj。如果被装饰的对象是一个函数,那么obj必须在函数创建时被实例化。如果被装饰的对象是一个方法,那么必须为类的每个实例实例化一个新的obj,并将其绑定到该实例。

2、解决方案

我们可以使用以下方法来解决这个问题:

  1. 使用inspect模块来获取被装饰对象的签名。
  2. 如果被装饰的对象是一个方法,则将obj绑定到self。
  3. 如果被装饰的对象是一个函数,则实例化obj。
  4. 返回一个新函数/方法,该函数/方法使用obj。

以下代码示例演示了如何实现此解决方案:

from types import InstanceType
from functools import wraps
import inspect

def dec(func):

   #get the sig of the function
   sig = []
   @wraps(func)
   def wrapper(*args, **kwargs):
      ret = None
      #if this is a method belonging to an object...
      if args and getattr(args[0], func.__name__, None):
         instance, args = args[0], args[1:]
         #if sig of object is not already set
         if not hasattr(instance, "sig"):
            instance.sig = []
         ret = func(instance, *args, **kwargs)
         print "Sig of %s is %s" % (func.__name__, id(instance.sig))
      #else this is a function
      else:
         ret = func(*args, **kwargs)
         print "Sig of %s is %s" % (func.__name__, id(sig))
      return ret

   #modify the doc string
   try:
      docs = inspect.getsourcelines(func)
   except:
      docs = "<unable to fetch defintion>"
   else:
      docs = docs[0][1].rstrip('\n').rstrip(':').lstrip(' ').lstrip('def')
   wrapper.__doc__ = docs + "\n" + (func.__doc__ or '')
   return wrapper

class A(object):
   def __init__(self):
      super(A, self).__init__()

   @dec
   def f(self, x):
      """something"""
      print '%s.f(%s)' % (self, x)


@dec
def myfunc():
   print "myfunc"

@dec
def myfunc2():
   print "myfunc2"

@dec
def myfunc3():
   print "myfunc3"

if __name__ == "__main__":
   list = []
   for x in xrange(3):
      list.append(A())

   [a.f(123) for a in list]
   myfunc()
   myfunc()
   myfunc2()
   myfunc2()
   myfunc3()
   myfunc3()

输出:

<__main__.A object at 0x00B9F2D0>.f(123)
Sig of f is 11932616
<__main__.A object at 0x00B9F430>.f(123)
Sig of f is 11925464
<__main__.A object at 0x00B9F450>.f(123)
Sig of f is 11918112
myfunc
Sig of myfunc is 11925624
myfunc
Sig of myfunc is 11925624
myfunc2
Sig of myfunc2 is 11794592
myfunc2
Sig of myfunc2 is 11794592
myfunc3
Sig of myfunc3 is 11925144
myfunc3
Sig of myfunc3 is 11925144

在这个示例中,dec装饰器用于在类A的方法f以及函数myfuncmyfunc2myfunc3上。当这些函数/方法被调用时,dec装饰器会将obj绑定到self(如果是方法)或实例化obj(如果是函数)。然后,dec装饰器会返回一个新函数/方法,该函数/方法使用obj。

请注意,这种解决方案只适用于对象obj在实例化时创建的情况。如果obj需要在其他时间创建,那么您需要修改此解决方案以适应您的具体情况。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值