带实例化时间变量的Python装饰器?

带实例化时间变量的Python装饰器?,python,decorator,Python,Decorator,我想制作一个装饰器,创建一个新函数/方法,该函数/方法使用对象obj。如果修饰对象是函数,则在创建函数时必须实例化obj。如果修饰对象是一个方法,则必须实例化一个新的obj,并将其绑定到其方法被修饰的类的每个实例。我不能将装饰放在\uuuu init\uuuu中,因为装饰器修改函数文档。我现在有这样的东西,但它只实例化了一次时间,这不是我想要的: __all__ = ['dec', 'A'] from time import time import inspect def dec(f):

我想制作一个装饰器,创建一个新函数/方法,该函数/方法使用对象
obj
。如果修饰对象是函数,则在创建函数时必须实例化obj。如果修饰对象是一个方法,则必须实例化一个新的
obj
,并将其绑定到其方法被修饰的类的每个实例。我不能将装饰放在
\uuuu init\uuuu
中,因为装饰器修改函数文档。我现在有这样的东西,但它只实例化了一次时间,这不是我想要的:

__all__ = ['dec', 'A']

from time import time
import inspect

def dec(f):
    obj = time() # want to set on object instantiation
    def new(*args, **kwargs):
        f(*args, **kwargs) # Validate against definition so it doesn't go
                           # out of sync
        print obj
        # ...
    try:
        d = inspect.getsourcelines(f)
    except IOError:
        d = "<unable to fetch definition>"
    else:
        d = d[0][1].rstrip('\n').rstrip(':').lstrip(' ').lstrip('def')
    new.__doc__ = d + "\n" + (f.__doc__ or '')
    return new

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

if __name__ == '__main__':
    A().f(123)
    A().f(123)
    A().f(123)
\uuuuu all\uuuuu=['dec','A']
从时间导入时间
进口检验
def dec(f):
obj=time()#是否要设置对象实例化
def新(*args,**kwargs):
f(*args,**kwargs)#根据定义进行验证,使其不会消失
#不同步
打印对象
# ...
尝试:
d=检查.getsourcelines(f)
除IOError外:
d=“”
其他:
d=d[0][1].rstrip('\n').rstrip(':').lstrip('').lstrip('def'))
新的._uu文件_uu=d+“\n”+(f._uu文件或“”)
还新
A类(对象):
@十二月
def f(自身,x):
“某物”
打印“%s.f(%s)”%(自身,x)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
A().f(123)
A().f(123)
A().f(123)
我解决这个问题的想法是检查传递给装饰器的对象是否接受参数
self
,如果是,则返回一个方法,该方法将
obj
绑定到
self
,如果它不在那里,然后使用
self.obj
。然后,如果传递给decorator的对象没有
self
参数,只需在decorator内实例化
obj
,并返回一个利用该参数的函数

然而。。。我所说的对我来说并不真正有效,因为在我真正的decorator中,我返回一个从
列表
派生的对象,该对象具有
\u调用
属性。此外,在真正的decorator中,
self
甚至没有在被它修饰的对象中定义,因为它们没有使用它们的实例变量(我真正修饰的只是外部对象订阅的事件,这些事件有文档化的签名)


编辑:实际上,如果有一种方法可以使
列表
子类实例绑定到一个实例,这样它的
调用
属性隐式地接收类实例(就像在任何普通的实例方法中一样),这将是一个完美的解决方案,这就是我最初试图解决的问题。但也许有更好的解决方案,这样我就不必用
self
属性定义修饰过的方法了?两者都是完美的。

因为装饰者只是用来表达的语法糖

def func():
   ...
func = decorator(func)
为什么不在对象构造函数中这样做呢

class A(object):
    def __init__(self):
        # apply decorator at instance creation
        self.f = dec(self.f)

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

因为一个装饰师只是一个语法糖

def func():
   ...
func = decorator(func)
为什么不在对象构造函数中这样做呢

class A(object):
    def __init__(self):
        # apply decorator at instance creation
        self.f = dec(self.f)

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

你的写作风格真的很难读。正常的句子只有你的一半长:P

你想要这个还是什么

__all__ = ['dec', 'A']

from time import time, sleep
import inspect

def dec(f):
    def new(self, *args, **kwargs):
        print self.initiated # print the time the objecte was initiated ...
        return f(self, *args, **kwargs) # Validate against definition so it doesn't go
                           # out of sync
    try:
        d = inspect.getsourcelines(f)
    except IOError:
        d = "<unable to fetch definition>"
    else:
        d = d[0][1].rstrip('\n').rstrip(':').lstrip(' ').lstrip('def')
    new.__doc__ = d + "\n" + (f.__doc__ or '')
    return new

class A(object):
    def __init__(self):
        self.initiated = time() # save the time the object was initiated


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

if __name__ == '__main__':
    A().f(123)
    sleep(1)
    A().f(123)
    sleep(1)
    A().f(123)
\uuuuu all\uuuuu=['dec','A']
从时间导入时间,睡眠
进口检验
def dec(f):
def新(自身、*args、**kwargs):
print self.initiated#打印对象启动的时间。。。
返回f(self,*args,**kwargs)#根据定义进行验证,使其不会消失
#不同步
尝试:
d=检查.getsourcelines(f)
除IOError外:
d=“”
其他:
d=d[0][1].rstrip('\n').rstrip(':').lstrip('').lstrip('def'))
新的._uu文件_uu=d+“\n”+(f._uu文件或“”)
还新
A类(对象):
定义初始化(自):
self.initiated=time()#保存启动对象的时间
@十二月
def f(自身,x):
“某物”
打印“%s.f(%s)”%(自身,x)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
A().f(123)
睡眠(1)
A().f(123)
睡眠(1)
A().f(123)

你的写作风格很难理解。正常的句子只有你的一半长:P

你想要这个还是什么

__all__ = ['dec', 'A']

from time import time, sleep
import inspect

def dec(f):
    def new(self, *args, **kwargs):
        print self.initiated # print the time the objecte was initiated ...
        return f(self, *args, **kwargs) # Validate against definition so it doesn't go
                           # out of sync
    try:
        d = inspect.getsourcelines(f)
    except IOError:
        d = "<unable to fetch definition>"
    else:
        d = d[0][1].rstrip('\n').rstrip(':').lstrip(' ').lstrip('def')
    new.__doc__ = d + "\n" + (f.__doc__ or '')
    return new

class A(object):
    def __init__(self):
        self.initiated = time() # save the time the object was initiated


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

if __name__ == '__main__':
    A().f(123)
    sleep(1)
    A().f(123)
    sleep(1)
    A().f(123)
\uuuuu all\uuuuu=['dec','A']
从时间导入时间,睡眠
进口检验
def dec(f):
def新(自身、*args、**kwargs):
print self.initiated#打印对象启动的时间。。。
返回f(self,*args,**kwargs)#根据定义进行验证,使其不会消失
#不同步
尝试:
d=检查.getsourcelines(f)
除IOError外:
d=“”
其他:
d=d[0][1].rstrip('\n').rstrip(':').lstrip('').lstrip('def'))
新的._uu文件_uu=d+“\n”+(f._uu文件或“”)
还新
A类(对象):
定义初始化(自):
self.initiated=time()#保存启动对象的时间
@十二月
def f(自身,x):
“某物”
打印“%s.f(%s)”%(自身,x)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
A().f(123)
睡眠(1)
A().f(123)
睡眠(1)
A().f(123)

要想弄清楚你到底想要什么有点困难。清单和电话之类的东西让我很困惑,所以我主要还是坚持你的第一段:

__all__ = ['dec', 'A']

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()
\uuuuu all\uuuuu=['dec','A']
从类型导入InstanceType
从functools导入包装
进口检验
def dec(func):
#获取函数的sig
sig=[]
@包装(func)
def包装(*args,**kwargs):
ret=无
#如果这是属于对象的方法。。。
如果args和getattr(args[0],函数名,无):
实例,args=args[0],args[1:]
#如果尚未设置对象的sig
如果不是hasattr(实例“sig”):
instance.sig=[]
ret=func(实例,*args,**kwargs)
打印“%s的Sig为%s%”(函数名,id(instance.Sig))
#否则这是一个函数
其他:
ret=func(*args,**kwargs)
打印“%s的Sig为%s%”(函数名称、id(Sig))
回程网
#修改文档字符串
尝试:
docs=inspect.getsourcelines(func)
除:
D
__all__ = ['dec', 'A']

from functools import wraps
import inspect

def dec(cls=None):
    # cls will be closed in subdec
    def subdec(func):
        # closed in wrapper, guaranteed to be unique per decorator evaluation
        obj = []

        @wraps(func)
        def wrapper(*args, **kwargs):
            if (args and type(args[0]) == cls):
                instance = args[0]
                # We will attach to instance a dict _objs of
                # function_name:obj. This way we don't pollute the namespace
                # when decorating many functions.

                # Alternatively, you could make a dict external to instance
                # of instance:{function_name:obj}, but that takes more work
                # because you need to make it not prevent garbage collection
                # of instance.
                if not hasattr(instance, "_objs"):
                    instance._objs = {}
                if func.__name__ not in instance._objs:
                    instance._objs[func.__name__] = []
                func(*args, **kwargs) # This is only used to check the arity.
                                      # My real code is all to do with
                                      # manipulating obj.
                print "obj of %s.%s is %s" % (
                    instance,
                    func.__name__,
                    id(instance._objs[func.__name__])
                )
            else:
                # Functions are identified by the closed obj
                func(*args, **kwargs)
                print "obj of %s is %s" % (func.__name__, id(obj))

        # Find function/method signature and prepend it to the new object's doc
        try:
            doc = inspect.getsourcelines(func)
        except IOError:
            line = "<unable to fetch definition>"
        else:
            line = '@'
            i = 0
            while line.lstrip(' ').startswith("@"):
                try:
                    line = doc[0][i]
                except IndexError:
                    line = "<unable to fetch definition>"
                i += 1
        line = line.rstrip('\n').rstrip(':').lstrip(' ').lstrip('def')
        wrapper.__doc__ = line + "\n" + (func.__doc__ or '')

        return wrapper
    return subdec

class A(object):
    def f(self, x):
        """something"""
        print '%s.f(%s)' % (self, x)

A.f = dec(A)(A.f)

@dec()
def myfunc():
    print "myfunc"

@dec()
def myfunc2():
    print "myfunc2"

@dec()
def myfunc3():
    print "myfunc3"

if __name__ == "__main__":
    a, b, c = A(), A(), A()
    # a, b, and c each have their own instance of obj:
    a.f(123)
    b.f(123)
    c.f(123)
    myfunc()
    myfunc()
    myfunc2()
    myfunc2()
    myfunc3()
    myfunc3()