首页 > 编程问答 >有没有办法将上下文管理器的上下文保留在 as 块本地?

有没有办法将上下文管理器的上下文保留在 as 块本地?

时间:2024-07-21 01:40:43浏览次数:11  
标签:python

我正在尝试找到一种方法来避免为传递给另一个函数的某些函数创建一堆名称。 我意识到,如果函数只是简单的表达式,那么我可以传入 lambda 并避免创建命名函数,但在许多情况下,它们是需要语句的较长函数。

这是我正在做的示例。这种方法工作正常,但需要我定义一个唯一的命名函数并将其传递到订阅函数中。

subscribers = []
def subscribe(handler):
    subscribers.append(handler)

def handler_1():
    print(f'handler 1')
subscribe(handler_1)

def handler_2():
    print(f'handler 2')
subscribe(handler_2)

for subscriber in subscribers:
    subscriber()

运行此方法会产生预期的效果:

handler 1
handler 2

我试图通过使用上下文管理器来解决此问题。 在每个宽度语句中,我希望创建一个简单命名为 handler 的闭包,并将其传递给 subscribe 函数。 但这不起作用,因为上下文变量似乎不是 as 块中的语句的本地变量,而是位于 with 语句之外的范围内。结果是每个 with / as 语句中定义的每个闭包捕获相同的上下文变量(来自最后一个 with 语句。

这是我希望避免创建一堆唯一命名的函数的示例。| ||所以上面的代码产生:

from contextlib import contextmanager
@contextmanager
def foo(target):
    yield target

subscribers = []
with foo('target 1') as context:
    def handler():
        print(f'target = {context}')
        return context
    subscribe(handler)

with foo('target 2') as context:
    def handler():
        print(f'target = {context}')
        return context
    subscribe(handler)

for subscriber in subscribers:
    subscriber()

我想最后我试图使用上下文管理器来实现类似尾随闭包的东西,但如果上下文变量不是本地的,这似乎是不可能的。 有没有办法避免我原来的方法,该方法有效但需要一堆命名函数,我觉得这可能容易出错?

target = target 2
target = target 2

I guess in the end I was trying to used a context manager to implement something like a trailing closure, but that does not seem possible if the context variable is not local. Is there a way to avoid my original approach, which works but requires a bunch of named functions, which I feel might be error prone?


对上下文管理器行为的理解是正确的。 as 子句中分配的变量范围与 with 语句本身相同,而不是 with 块内部。这意味着在的示例中,两个处理程序最终都引用了同一个 context 变量,该变量在第二个 with 语句中被更新为“target 2”。

但是,无需上下文管理器即可实现目标。Python 支持 闭包 匿名函数(lambda) ,这可以帮助实现简洁的解决方案。

以下是使用 lambda 表达式实现的目标的重构代码:

subscribers = []
def subscribe(handler):
    subscribers.append(handler)

def foo(target):
    def handler():
        print(f'target = {target}')
        return target
    return handler

subscribe(foo('target 1'))
subscribe(foo('target 2'))

for subscriber in subscribers:
    subscriber()

在此版本中:

  1. foo 函数现在是一个闭包工厂。 它接受 target 作为参数,并定义一个新的 handler 函数,该函数在其内部作用域中捕获 target 。然后 foo 返回此 handler 函数。

  2. 我们使用 foo('target 1') foo('target 2') 直接将创建的处理程序订阅到 subscribe 这利用了闭包,确保每个处理程序都保持其自己的 target 值,而无需单独命名函数。

此方法避免了不必要的命名函数,同时保持了代码的清晰性和可读性。它还利用了 Python 闭包的强大功能来管理每个处理程序的范围。

标签:python
From: 78773339

相关文章

  • 有人可以解决我的代码中的问题吗?而且我无法在我的电脑上安装 nsetools。如何在 python
    从nsetools导入Nseimportpandasaspdnse=Nse()all_stock_codes=nse.get_stock_codes()companies_with_low_pe=[]对于all_stock_codes中的代码:如果代码=='符号':继续尝试:stock_quote=nse.get_quote(代码)pe_ratio=stock_quote.get('priceT......
  • 将 python 脚本的 stdin 重定向到 fifo 会导致 RuntimeError: input():lost sys.stdin
    我有这个python脚本,它的作用是充当服务器,它从重定向到fifo的stdin读取命令:test.py:whileTrue:try:line=input()exceptEOFError:breakprint(f'Received:{line}')在bash中运行命令:mkfifotestfifotest.py<testfifo......
  • Python/Flask mysql 游标:为什么它不起作用?
    fromflaskimportFlaskfromflask_mysqldbimportMySQLapp=Flask(__name__)app.config['MYSQL_HOST']='localhost'app.config['MYSQL_USER']='root'app.config['MYSQL_PASSWORD']='password'a......
  • Python pandas to_csv 导致 OSError: [Errno 22] 参数无效
    我的代码如下:importpandasaspdimportnumpyasnpdf=pd.read_csv("path/to/my/infile.csv")df=df.sort_values(['distance','time'])df.to_csv("path/to/my/outfile.csv")此代码成功从infile.csv(一个3GBcsv文件)读取数据,对其进行排......
  • 从 python 中的字符串列表中提取 def 定义函数的标签
    我想使用Python中的正常def过程创建函数,并将标签分配给从字符串列表中提取的命名空间。如何实现这一点?这个问题的动机:我正在创建一个与sympy兼容的python函数库,供数学家用于符号计算实验。许多函数需要初始化具有相关标签的多个对象的系统,这些标签分别由用户提供的字......
  • 在 Raspberry Pi 4 上使用 Python 从具有 SPI 连接的 MT6816 磁性编码器读取
    我对这个领域完全陌生,并不真正知道自己在做什么并且需要帮助。我正在尝试使用MT681614位磁性编码器通过RaspberryPi的SPI连接读取绝对角度。我有以下问题:在硬件方面,是否只是简单地连接必要的连接(3.3V、MOSI、MISO、SCK、GND、CE01)?对于编码......
  • PythonW 不运行脚本。严重地
    因此,使用Windows10和Python3.6。我创建了一个.py脚本,它可以使用命令pythonmyscript.py在命令提示符下正常运行,但是当我制作该脚本的精确副本并为其赋予扩展名.pyw,并尝试使用pythonw运行它时命令pythonwmyscript.pyw,什么也没有发生......
  • 如何使用Python和Selenium模拟产品购买以获取库存信息
    我正在开发一项网络抓取服务,主要针对时尚行业。我的目标是提供有关产品的全面数据,包括库存水平。为了实现这一目标,我需要模拟购买以确定每种尺寸的产品的最大可用数量。我一直在使用Python和Selenium进行网络抓取部分,但在准确模拟购买方面面临着挑战检索股票信息的过程。......
  • 连接Python套接字的问题
    当我写“关闭”时,我试图让我的电报机器人关闭计算机。我不想将机器人连接到网站上的托管。我选择我的手机(AndroidRedmiNote10)作为托管。我在上面安装了Termux和Pydroid。我写了两个文件:main到我的电脑,client到我的手机。通过在计算机上运行这两个文件,一切正常。但是,当我在......
  • 如何修复导入 Numexpr Python 时的错误
    在Windows10Python3.7.9(IDLE)上,我成功安装了“pipinstallnumexpr”,但在“importnumexprasne”时出现错误:Traceback(最近一次调用):文件“<pyshell#21>”,第267行,位于将numexpr导入为ne文件“C:\Python379\lib\site-packages\numexpr_init_.py”......