Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python ContextManager使用块访问调用的局部变量()_Python_Scope - Fatal编程技术网

Python ContextManager使用块访问调用的局部变量()

Python ContextManager使用块访问调用的局部变量(),python,scope,Python,Scope,我正在尝试编写一个带有上下文管理器的多线程助手。其思想是在一个块中定义一组函数,上下文管理器“神奇地”处理调度和所有事情。简化的工作版本如下所示: import contextlib @contextlib.contextmanager def multi_threaded(count): funcs = [] yield funcs my_slice = int(count / len(funcs)) for i, func in enumerate(func

我正在尝试编写一个带有上下文管理器的多线程助手。其思想是在一个块中定义一组函数,上下文管理器“神奇地”处理调度和所有事情。简化的工作版本如下所示:

import contextlib

@contextlib.contextmanager
def multi_threaded(count):
    funcs = []
    yield funcs
    my_slice = int(count / len(funcs))
    for i, func in enumerate(funcs):
        start = my_slice * i
        func(start, start + my_slice)   


def spawn_many():
    dataset = [1, 2, 3, 4, 5]
    with multi_threaded(len(dataset)) as mt:
        def foo(start_idx, end):
            print("foo" + str(dataset[start_idx : end]))
        def bar(start_idx, end):
            print("bar" + str(dataset[start_idx : end]))
        mt.append(foo)
        mt.append(bar)

spawn_many()
这个例子很有效,但我想去掉以下几行:

        mt.append(foo)
        mt.append(bar)
因此,用户只需定义函数,而无需将其添加到集合中。为什么?因为它不太容易出错,而且我无法控制使用此库编写的代码

问题是,在收益之后,我不在发生
def foo
的范围内,因此我不知道该范围内存在的
locals()
,这基本上就是我需要知道哪些函数是在其中定义的。有什么想法/技巧/鼓励的话吗


谢谢你的阅读

装饰师可能会更好一些:

import contextlib

@contextlib.contextmanager
def multi_threaded(count):
    funcs = []
    yield funcs
    my_slice = int(count / len(funcs))
    for i, func in enumerate(funcs):
        start = my_slice * i
        func(start, start + my_slice)   

def add_to_flist(mt):
    def _add_to_flist(func):
        mt.append(func)
        return func
    return _add_to_flist

def spawn_many():
    dataset = [1, 2, 3, 4, 5]
    with multi_threaded(len(dataset)) as mt:
        @add_to_flist(mt)
        def foo(start_idx, end):
            print("foo" + str(dataset[start_idx : end]))
        @add_to_flist(mt)
        def bar(start_idx, end):
            print("bar" + str(dataset[start_idx : end]))

spawn_many()
我读到,至少没有丑陋的黑客,但我认为我的解决方案最终并没有那么丑陋:

您在创建时将
locals()
字典传递到contextmanager,contextmanager在屈服后查询该字典,以收集任何可调用项:

@contextlib.contextmanager
def多线程(阻塞局部变量,计数):
产量
funcs=[fn表示块中的fn_locals.values()如果可调用(fn)]
my_slice=int(count/len(funcs))
对于i,枚举中的func(funcs):
开始=我的切片*i
func(开始,开始+我的切片)
def spawn_many():
数据集=[1,2,3,4,5]
使用多线程(局部变量(),len(数据集)):
def foo(开始、结束):
打印(“foo”+str(数据集[start\u idx:end]))
def bar(开始\u idx,结束):
打印(“条”+str(数据集[start\u idx:end]))
#重新同步先前传递给multi_threaded()的本地指令。
本地人()
产生许多

请注意,由于最后一次调用块中的
locals()。似乎只有在调用
locals()
时,Python才会同步
locals()
字典函数局部变量。如果没有最后一次调用,
多线程
会将
{'dataset':[1,2,3,4,5]}
视为局部变量。

是的,这看起来肯定要好得多。我将把这个问题留一段时间不回答,因为我仍然希望找到一种解决方案,它不需要用户可能会漏掉的代码行。您找到更好的解决方案了吗?