是否可以在没有exec()的情况下自动使模块的所有公共类方法都成为全局函数?以turtle.py为例

2024-09-30 01:31:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我看到它声称exec()从来都不是必要的,应该总是避免。虽然99.9%的时间里都有更好的方法做事情,但我在查看turtle.py时发现:

## The following mechanism makes all methods of RawTurtle and Turtle available
## as functions. So we can enhance, change, add, delete methods to these
## classes and do not need to change anything here.

__func_body = """\
def {name}{paramslist}:
    if {obj} is None:
        if not TurtleScreen._RUNNING:
            TurtleScreen._RUNNING = True
            raise Terminator
        {obj} = {init}
    try:
        return {obj}.{name}{argslist}
    except TK.TclError:
        if not TurtleScreen._RUNNING:
            TurtleScreen._RUNNING = True
            raise Terminator
        raise
"""

def _make_global_funcs(functions, cls, obj, init, docrevise):
    for methodname in functions:
        method = getattr(cls, methodname)
        pl1, pl2 = getmethparlist(method)
        if pl1 == "":
            print(">>>>>>", pl1, pl2)
            continue
        defstr = __func_body.format(obj=obj, init=init, name=methodname,
                                    paramslist=pl1, argslist=pl2)
        exec(defstr, globals())
        globals()[methodname].__doc__ = docrevise(method.__doc__)

_make_global_funcs(_tg_screen_functions, _Screen,
                   'Turtle._screen', 'Screen()', _screen_docrevise)
_make_global_funcs(_tg_turtle_functions, Turtle,
                   'Turtle._pen', 'Turtle()', _turtle_docrevise)

这段代码就是为什么初学者使用海龟模块如此方便的原因。除了海龟类实例根据需要自动分配自己的屏幕外,这种“机制”还自动将每个公共类方法变成一个全局函数。这就是为什么这样的代码不会直接实例化任何海龟类:

import turtle
turtle.forward(100)
turtle.mainloop()

这将实例化一个屏幕,实例化一个海龟,将屏幕分配给海龟,调用该海龟实例的一个方法来画一条线,并调用该屏幕的一个方法来保持窗口打开,所有这些都带有自动生成的全局函数。这是我见过的最好的exec()用例

有没有一种方法可以在不使用exec()的情况下以更pythonical的方式执行此操作


Tags: 实例方法objifinitfunctionsrunningexec
1条回答
网友
1楼 · 发布于 2024-09-30 01:31:20

下面是如何在没有exec()的情况下复制此功能的。。。有点

exec()对于以显式方式将旧的调用签名分配给新的全局函数仍然是必需的,没有方便的方法为函数指定新的调用签名

但是,作为对我问题的回答,闭包可以将方法转换为全局函数,调用签名必须是*args, **kwargs

下面的代码似乎代替了我发布的代码,并回答了我的问题标题“如何在没有exec的情况下复制making methods全局函数”,尽管我认为由于缺少准确的签名,它并不更像Python:

def __turtle_func_closure(obj, init, name):
    """Wraps class methods as global functions."""

    def func(*args, **kwargs):
        """Global function equivalent ofor class methods."""
        obj_ = getattr(Turtle, obj, None)
        if obj_ is None:
            if not TurtleScreen._RUNNING:
                TurtleScreen._RUNNING = True
                raise Terminator
            obj_ = init()
        try:
            return getattr(obj_, name)(*args, **kwargs)
        except TK.TclError:
            if not TurtleScreen._RUNNING:
                TurtleScreen._RUNNING = True
                raise Terminator
            raise

    return func


def _make_global_funcs(functions, cls, obj, init, docrevise):
    for methodname in functions:
        method = getattr(cls, methodname)

        globals()[methodname] = __turtle_func_closure(obj, init, methodname)
        globals()[methodname].__doc__ = docrevise(method.__doc__)

_make_global_funcs(_tg_screen_functions, _Screen,
                   'Turtle._screen', Screen, _screen_docrevise)
_make_global_funcs(_tg_turtle_functions, Turtle,
                   'Turtle._pen', Turtle, _turtle_docrevise)

相关问题 更多 >

    热门问题