Python 影响系统的装饰器\u getframe(1)

Python 影响系统的装饰器\u getframe(1),python,python-2.x,python-decorators,Python,Python 2.x,Python Decorators,a.py import d d.funcme('blah') import sys import Errors def argcheck(in_=(), out=(type(None),)): def _argcheck(function): # do something here def __argcheck(*args, **kw): print '+++++++++ checking types before callin

a.py

import d

d.funcme('blah')
import sys
import Errors
def argcheck(in_=(), out=(type(None),)):
    def _argcheck(function):
        # do something here
        def __argcheck(*args, **kw):
            print '+++++++++ checking types before calling the func'
            # do something here
            res = function(*args, **kw)
            return res
        return __argcheck
    return _argcheck

@argcheck((str))       <-----
def funcme(name):
    try:
        f = sys._getframe(1)
    except ValueError, err:
        raise Errors.UserError(err)     # stack too deep
        filename, lineno = f.f_globals['__name__'], f.f_lineno
    print filename, lineno
d.py

import d

d.funcme('blah')
import sys
import Errors
def argcheck(in_=(), out=(type(None),)):
    def _argcheck(function):
        # do something here
        def __argcheck(*args, **kw):
            print '+++++++++ checking types before calling the func'
            # do something here
            res = function(*args, **kw)
            return res
        return __argcheck
    return _argcheck

@argcheck((str))       <-----
def funcme(name):
    try:
        f = sys._getframe(1)
    except ValueError, err:
        raise Errors.UserError(err)     # stack too deep
        filename, lineno = f.f_globals['__name__'], f.f_lineno
    print filename, lineno
使用
argcheck
decorator输出:

$ python a.py  
+++++++++ checking types before calling the func  
defines 9  
问题:

  • decorator是如何更改
    \u getframe
    的值的

  • 如何保存信息,使其捕获原始信息,即
    \uuuuu main\uuuu
    3而不是定义9


  • Decorator基本上是语法糖。这:

    @argcheck((str))
    def funcme(name):
    
    与此相同:

    funcme = argcheck(str)(funcme)
    
    现在,您可以了解装饰程序更改调用堆栈的原因了


    我不知道如何在任意情况下解决这个问题,但是如果您事先知道一些关于装饰器的信息,您也许可以为此对代码进行补偿。您还可以研究一下,也许这会提供一些可能有用的线索。

    Decorator基本上是语法糖。这:

    @argcheck((str))
    def funcme(name):
    
    与此相同:

    funcme = argcheck(str)(funcme)
    
    现在,您可以了解装饰程序更改调用堆栈的原因了


    我不知道如何在任意情况下解决这个问题,但是如果您事先知道一些关于装饰器的信息,您也许可以为此对代码进行补偿。您还可以研究一下,也许这会提供一些可能有用的线索。

    Decorator基本上是语法糖。这:

    @argcheck((str))
    def funcme(name):
    
    与此相同:

    funcme = argcheck(str)(funcme)
    
    现在,您可以了解装饰程序更改调用堆栈的原因了


    我不知道如何在任意情况下解决这个问题,但是如果您事先知道一些关于装饰器的信息,您也许可以为此对代码进行补偿。您还可以研究一下,也许这会提供一些可能有用的线索。

    Decorator基本上是语法糖。这:

    @argcheck((str))
    def funcme(name):
    
    与此相同:

    funcme = argcheck(str)(funcme)
    
    现在,您可以了解装饰程序更改调用堆栈的原因了


    我不知道如何在任意情况下解决这个问题,但是如果您事先知道一些关于装饰器的信息,您也许可以为此对代码进行补偿。您还可以研究一下,也许这会提供一些可能有用的线索。

    问题是您的
    funcme()
    函数假定它是通过其他东西直接调用的,而不是通过其他东西间接调用的,例如装饰器。可以通过更改其调用顺序并添加一个附加的带有默认值的
    depth
    关键字参数来修复此问题,该参数将传递给
    \u sys.\u getframe()
    。有了这个脚手架,装饰者就可以覆盖默认值。无论是否应用了装饰器,以下内容都将打印相同的内容:

     1 import sys
     2 import Errors
     3 def argcheck(in_=(), out=(type(None),)):
     4     def _argcheck(function):
     5         # do something here
     6         def __argcheck(*args, **kw):
     7             print '+++++++++ checking types before calling the func'
     8             # do something here
     9             res = function(*args, depth=2, **kw)  # override default depth
    10             return res
    11         return __argcheck
    12     return _argcheck
    13
    14 @argcheck((str))
    15 def funcme(name, depth=1):  # added keyword arg with default value
    16     try:
    17         f = sys._getframe(depth)   # explicitly pass stack depth wanted
    18     except ValueError, err:
    19         raise Errors.UserError(err)     # stack too deep
    20
    21     filename, lineno = f.f_globals['__name__'], f.f_lineno
    22     print filename, lineno
    

    问题是,您的
    funcme()
    函数假定它是通过其他对象(例如装饰器)直接调用的,而不是间接调用的。可以通过更改其调用顺序并添加一个附加的带有默认值的
    depth
    关键字参数来修复此问题,该参数将传递给
    \u sys.\u getframe()
    。有了这个脚手架,装饰者就可以覆盖默认值。无论是否应用了装饰器,以下内容都将打印相同的内容:

     1 import sys
     2 import Errors
     3 def argcheck(in_=(), out=(type(None),)):
     4     def _argcheck(function):
     5         # do something here
     6         def __argcheck(*args, **kw):
     7             print '+++++++++ checking types before calling the func'
     8             # do something here
     9             res = function(*args, depth=2, **kw)  # override default depth
    10             return res
    11         return __argcheck
    12     return _argcheck
    13
    14 @argcheck((str))
    15 def funcme(name, depth=1):  # added keyword arg with default value
    16     try:
    17         f = sys._getframe(depth)   # explicitly pass stack depth wanted
    18     except ValueError, err:
    19         raise Errors.UserError(err)     # stack too deep
    20
    21     filename, lineno = f.f_globals['__name__'], f.f_lineno
    22     print filename, lineno
    

    问题是,您的
    funcme()
    函数假定它是通过其他对象(例如装饰器)直接调用的,而不是间接调用的。可以通过更改其调用顺序并添加一个附加的带有默认值的
    depth
    关键字参数来修复此问题,该参数将传递给
    \u sys.\u getframe()
    。有了这个脚手架,装饰者就可以覆盖默认值。无论是否应用了装饰器,以下内容都将打印相同的内容:

     1 import sys
     2 import Errors
     3 def argcheck(in_=(), out=(type(None),)):
     4     def _argcheck(function):
     5         # do something here
     6         def __argcheck(*args, **kw):
     7             print '+++++++++ checking types before calling the func'
     8             # do something here
     9             res = function(*args, depth=2, **kw)  # override default depth
    10             return res
    11         return __argcheck
    12     return _argcheck
    13
    14 @argcheck((str))
    15 def funcme(name, depth=1):  # added keyword arg with default value
    16     try:
    17         f = sys._getframe(depth)   # explicitly pass stack depth wanted
    18     except ValueError, err:
    19         raise Errors.UserError(err)     # stack too deep
    20
    21     filename, lineno = f.f_globals['__name__'], f.f_lineno
    22     print filename, lineno
    

    问题是,您的
    funcme()
    函数假定它是通过其他对象(例如装饰器)直接调用的,而不是间接调用的。可以通过更改其调用顺序并添加一个附加的带有默认值的
    depth
    关键字参数来修复此问题,该参数将传递给
    \u sys.\u getframe()
    。有了这个脚手架,装饰者就可以覆盖默认值。无论是否应用了装饰器,以下内容都将打印相同的内容:

     1 import sys
     2 import Errors
     3 def argcheck(in_=(), out=(type(None),)):
     4     def _argcheck(function):
     5         # do something here
     6         def __argcheck(*args, **kw):
     7             print '+++++++++ checking types before calling the func'
     8             # do something here
     9             res = function(*args, depth=2, **kw)  # override default depth
    10             return res
    11         return __argcheck
    12     return _argcheck
    13
    14 @argcheck((str))
    15 def funcme(name, depth=1):  # added keyword arg with default value
    16     try:
    17         f = sys._getframe(depth)   # explicitly pass stack depth wanted
    18     except ValueError, err:
    19         raise Errors.UserError(err)     # stack too deep
    20
    21     filename, lineno = f.f_globals['__name__'], f.f_lineno
    22     print filename, lineno