带实例化时间变量的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()