Python 中的 RAII - 离开范围时自动销毁

2023-12-26

我一直在努力寻找RAII https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization在Python中。 资源分配即初始化是 C++ 中的一种模式,其中 对象在创建时就被初始化。如果失败,则会抛出 一个例外。这样,程序员就知道了 该对象永远不会处于半构建状态。 Python 能做到这么多。

但 RAII 也适用于 C++ 的作用域规则 以确保对象的及时销毁。一旦变量 从堆栈中弹出并被销毁。这可能发生在 Python 中,但仅限于 如果没有外部或循环引用。

更重要的是,对象的名称仍然存在,直到它被调用为止 在出口处(有时更长)。模块级别的变量将 在模块的使用寿命内坚持使用。

如果我做这样的事情,我想得到一个错误:

for x in some_list:
    ...

... 100 lines later ...

for i in x:
    # Oops! Forgot to define x first, but... where's my error?
    ...

我可以在使用后手动删除这些名称, 但这会很丑陋,并且需要我付出努力。

在这种情况下,我希望它按照我的意思去做:

for x in some_list:
    surface = x.getSurface()
    new_points = []
    for x,y,z in surface.points:
        ...     # Do something with the points
        new_points.append( (x,y,z) )
    surface.points = new_points
    x.setSurface(surface)

Python 做了一些范围界定,但不是在缩进级别,只是在 功能级别。要求我创建一个新函数似乎很愚蠢 只是为了确定变量的范围,以便我可以重用名称。

Python 2.5 有“与”语句 http://www.python.org/dev/peps/pep-0343/但这需要我明确输入__enter__ and __exit__功能 通常似乎更倾向于清理文件等资源 和互斥锁,无论退出向量如何。它对范围界定没有帮助。 或者我错过了什么?

我搜索了“Python RAII”和“Python scope”,但找不到任何内容 直接且权威地解决了这个问题。 我已经查看了所有 PEP。这个概念似乎没有得到解决 在 Python 中。

因为我想在 Python 中定义作用域变量,所以我是一个坏人吗? 这是不是太不Pythonic了?

我这不是在摸索吗?

也许我正试图剥夺该语言动态方面的好处。 有时想要强制执行范围是自私吗?

我是否懒惰想要编译器/解释器 捕捉我疏忽的变量重用错误?嗯,是的,我当然很懒, 但我是不是太懒了?


tl;drRAII 是不可能的,你将它与一般的作用域混合在一起,当你错过那些额外的作用域时,你可能会编写糟糕的代码。

也许我没有明白你的问题,或者你没有得到关于 Python 的一些非常重要的东西......首先,与作用域相关的确定性对象销毁是不可能的用垃圾收集语言。 Python 中的变量仅仅是引用。你不会想要一个malloc'd 内存块free一旦指向它的指针超出范围,你会吗?实际例外情况some如果您碰巧使用引用计数,那么没有一种语言会疯狂到能够一成不变地设置确切的实现。

And even if你有引用计数,就像在 CPython 中一样,它是一个实现细节。一般来说,包括Python,它有多种实现not使用引用计数,您应该像每个对象都挂起直到内存耗尽一样进行编码。

至于函数调用其余部分现有的名称:can通过以下方式从当前或全局范围中删除名称del陈述。然而,这与手动内存管理无关。它只是删除引用。这可能会也可能不会触发引用的对象被 GC,这不是练习的重点。

  • 如果您的代码足够长,会导致名称冲突,那么您应该编写较小的函数。并使用更具描述性、不太可能发生冲突的名称。嵌套循环覆盖外循环的迭代变量也是如此:我还没有遇到这个问题,所以也许你的名字描述性不够,或者你应该将这些循环分开?

你是对的,with与范围界定无关,只与确定性清理有关(因此它在末端与 RAII 重叠,但在方法上不重叠)。

也许我正试图剥夺该语言动态方面的好处。有时想要强制执行范围是自私吗?

不。良好的词法作用域是一个独立于动态/静态的优点。不可否认,Python(2 - 3 几乎修复了这个问题)在这方面有弱点,尽管它们更多地处于闭包领域。

但要解释“为什么”:Pythonmust对于开始新作用域的位置要保守,因为如果没有另外声明,对名称的赋值会使其成为最内部/当前作用域的本地名称。所以例如如果 for 循环有自己的作用域,则无法轻松修改循环之外的变量。

我是否懒惰地希望编译器/解释器捕获我疏忽的变量重用错误?嗯,是的,我当然很懒,但是我是不是很懒呢?

再次,我认为意外地重用名称(以引入错误或陷阱的方式)是罕见的,而且无论如何都是小事。

编辑:为了尽可能清楚地再次说明这一点:

  • 使用 GC 的语言不能进行基于堆栈的清理。根据定义,这是不可能的:变量是对堆上对象的潜在许多引用之一,这些对象既不知道也不关心变量何时超出范围,并且所有内存管理都由 GC 负责,GC 会在变量超出范围时运行喜欢,而不是在弹出堆栈帧时。资源清理的解决方式不同,见下文。
  • 确定性清理通过以下方式发生with陈述。是的,它没有引入新的范围(见下文),因为这不是它的用途。托管对象绑定的名称没有被删除并不重要 - 尽管如此,清理还是发生了,剩下的是“不要碰我,我不可用”对象(例如关闭的文件流)。
  • Python 对每个函数、类和模块都有一个作用域。时期。这就是语言的工作原理,无论你喜欢与否。如果您想要/“需要”更细粒度的范围,请将代码分解为更细粒度的函数。您可能希望有更细粒度的范围,但没有 - 并且由于本答案前面指出的原因(“编辑:”上方的三段),这是有原因的。不管你喜欢与否,但这就是语言的工作原理。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中的 RAII - 离开范围时自动销毁 的相关文章

随机推荐

  • 使用 Spring.Net 将依赖项注入 ASP.NET MVC ActionFilters

    我正在使用 MvcContrib 进行 Spring Net ASP Net MVC 控制器依赖项注入 我的依赖项没有被注入到我的 CustomAttribute 操作过滤器中 如何将我的依赖项放入其中 假设您有一个 ActionFilte
  • 为什么 Any 比 Contains 慢?

    我设计了以下测试 var arrayLength 5000 object objArray new object arrayLength for var x 0 x
  • 如何在 R 中进行样本量不等的单向方差分析?

    尝试学习 R 旧统计文本中的一个问题想知道不同建筑工地的休息时间是否存在差异 问题是 文本决定每个站点雇用不同数量的工人 因此 我陷入困境并寻求使用样本量不等的方差分析的帮助 site1 lt c 34 25 27 31 26 34 21
  • 在 Java 中,可以在迭代列表时修改列表吗?

    据我所知 在Java中Collection
  • 使用已知物体尺寸从图片中测量物体

    所以我需要做的是从普通用户拍摄的图像中测量脚长 该图像将包含一只穿着黑色袜子的脚 一枚硬币 或其他已知尺寸的物体 和一张白纸 例如 A4 其他两个物体将位于其上 我已经拥有什么了 我已经使用过 opencv 但只是简单的项目 我已经开始阅读
  • JqueryUI 自动完成:每个列表项仅显示一个字符

    我在用着jquery 1 4 2 min and jquery ui 1 8 6 custom要在 jsp 页面上获取自动完成数据 代码片段如下 document ready function input airportfrom autoc
  • rMarkdown 中是否可以有可排序(交互式)表格?

    我在用kable from knitr包来显示 html 文档上的表格 是否可以使其可排序 一些示例代码 title Test output html document r echo FALSE comment kable data fra
  • 如何在 mysql 存储过程中使用 case-when 语句?

    我想使用 request time 参数自动设置 session id 因此我选择了包含 case 语句的 mysql 存储过程 就这样 create procedure upd userinput in request time time
  • Plotly - 我想根据条件用不同的颜色为每个 X 轴值着色

    语言 JavaScript框架 情节 我有一个要求 我希望 x 轴值单独着色 而不是对 x 轴中的所有值着色 我尝试了下面的代码 但它对轴上的所有值执行相同的操作 此处 颜色 红色 应用于 x 轴上的所有值 我需要根据下面代码中数组 col
  • 如何在本地主机上测试打开的图

    我做了很多研究 但还没有找到明确的答案 有没有办法在本地主机上测试开放图 我在 locahost 上使用图形 api 没有任何问题 我已经在应用程序设置中更改了我的网站网址 甚至尝试在主机文件中设置一个域 但打开图的调试器 linter 尝
  • Stimulsoft - 如何在 asp.net core 中渲染报告并以角度显示

    刺激软件报告 https www stimulsoft com en documentation online programming manual index html 如何在 asp net core 中渲染报告及其变量和参数并以角度显
  • 如何为 IE 提供特殊的 CSS?

    我想为 ie8 使用一些不同的 CSS 但只保留一个 CSS 文件 谁能告诉我最好的 黑客 是什么 是的 我知道 hack 不好 但我想至少暂时保留一个 CSS 文件 例如 在非 IE8 浏览器中我希望浏览器看到以下内容 div conte
  • R:具有重复时间索引条目的时间序列

    我是 R 的 n00b 和堆栈溢出的 n00b 刚刚加入 所以如果我未能使用标记 我不知道 或错过了自述文件中的某些内容 请原谅我 如果您不介意 我将在这里解决我的完整问题 因为也许您可能会好心地告诉我应该如何最好地解决这个问题 Stage
  • Symfony:是否可以为组件设置模板?

    组件没有 setTemplate 我知道 但也许还有另一种方法可以做到这一点 问题似乎是关于 php 框架 http www symfony project org http www symfony project org sfCompon
  • 使用 Jumbotron 容器的输入组大于 Bootstrap 3 中的输入

    我正在使用 Bootstrap 3 输入组尝试一种奇怪的行为 当我将输入组插件 文本或图标 添加到大屏幕内的表单时 输入组高度大于其输入高度 在这里你可以找到一个 JsFiddle 和有问题的屏幕截图 div class jumbotron
  • 检查某项是否存在,如果不存在则报错

    我想使用 PowerShell 检查 IIS Web 应用程序是否存在 或可能存在其他类型的项目 我可以这样做Get Item 但是如果该项目不存在 则会报告错误 这会误导运行脚本的用户 看起来好像出了问题 而实际上一切都很好 我该如何做到
  • 如何终止 MySQL 连接

    我正在使用 MySQL 构建一个网站 我正在使用 TOAD for MySQL 突然无法连接到数据库 因为出现错误 太多联系 Toad for MySQL 是否有任何方法可以查看现有连接以便能够终止它们或简单地关闭所有连接 不 有没有内置
  • 休眠:内存问题?缺点?

    我正在使用 Hibernate 3 6 直到今天我还没有发现使用它的任何缺点 但今天有人告诉我 当项目变大时 使用 Hibernate 的应用程序会出现内存问题 发生这种情况是因为与不使用 hibernate 的应用程序相比 需要创建和存储
  • Flutter 在 facebook 应用 android 和 ios 中打开 facebook 链接

    在我的应用程序中 我存储了 Facebook 网址 我想在 Facebook 应用程序中打开它们 而不是在浏览器中 我尝试使用flutter url launcher 包但它在默认浏览器中打开链接 我想要的是直接打开链接进入脸书应用程序 谁
  • Python 中的 RAII - 离开范围时自动销毁

    我一直在努力寻找RAII https en wikipedia org wiki Resource acquisition is initialization在Python中 资源分配即初始化是 C 中的一种模式 其中 对象在创建时就被初始