我正在编写一个装饰器,并且出于各种恼人的原因[0],检查它包装的函数是独立定义还是作为类的一部分定义(以及新类继承哪些类)是有利的. .
例如:
def my_decorator(f):
defined_in_class = ??
print "%r: %s" %(f, defined_in_class)
@my_decorator
def foo(): pass
class Bar(object):
@my_decorator
def bar(self): pass
Run Code Online (Sandbox Code Playgroud)
应打印:
<function foo …>: False
<function bar …>: True
Run Code Online (Sandbox Code Playgroud)
另外,请注意:
typeof或inspect)将不起作用.[0]:具体来说,我正在编写一个装饰器,可以很容易地进行参数化测试nose.然而,nose将不会运行的子类测试发生器unittest.TestCase,所以我想我的装饰器能够确定它是否正在使用的一个子类中,TestCase并且不能用一个适当的错误.显而易见的解决方案-利用isinstance(self, TestCase)调用包装的函数之前是不行的,因为包装的功能需要是一个发生器,它没有得到执行,在所有.
Bra*_*des 13
看一下inspect.stack()包装方法时的输出.当装饰器的执行正在进行时,当前的堆栈帧是对装饰器的函数调用; 下一个堆栈帧向下是@正在应用于新方法的包装操作; 第三帧将是类定义本身,它具有单独的堆栈帧,因为类定义是它自己的命名空间(在完成执行时被包装起来创建一个类).
因此我建议:
defined_in_class = (len(frames) > 2 and
frames[2][4][0].strip().startswith('class '))
Run Code Online (Sandbox Code Playgroud)
如果所有这些疯狂的索引看起来都不可维护,那么你可以通过逐帧拆开框架来更加明确,如下所示:
import inspect
frames = inspect.stack()
defined_in_class = False
if len(frames) > 2:
maybe_class_frame = frames[2]
statement_list = maybe_class_frame[4]
first_statment = statement_list[0]
if first_statment.strip().startswith('class '):
defined_in_class = True
Run Code Online (Sandbox Code Playgroud)
请注意,在您的包装器运行时,我没有任何方式向Python询问类名称或继承层次结构; 这一点在处理步骤中"太早",因为类创建尚未完成.要么解析以class你自己开头的那一行,然后查看那个框架的全局变量以找到超类,要么在frames[1]代码对象周围查看你能学到什么 - 似乎类名最终出现frames[1][0].f_code.co_name在上面的代码中,但是我在类创建完成时,找不到任何方法来学习将要附加的超类.
| 归档时间: |
|
| 查看次数: |
3273 次 |
| 最近记录: |