【问题标题】:How Python deals with objects that come from "elsewhere"Python 如何处理来自“其他地方”的对象
【发布时间】:2019-02-07 16:49:41
【问题描述】:

这可能是一个愚蠢的问题,但我不明白 Python 中我们如何使用我们没有定义或导入的对象。

考虑以下示例,使用 Python 的 datetime 模块:

from datetime import date

date1 = date(2019,1,1)
date2 = date(2019,1,5)

type(date2-date1) #<class 'datetime.timedelta'>
type(date2)       #<class 'datetime.date'>

那么date2-date1 属于timedelta 类,即使我们还没有导入它。

(我可能还可以制作其他示例,我们可以在其中获取对象,即使我们还没有定义它们。)

这怎么可能?

我是否应该考虑一下这些新对象只是作为内存中的片段弹出,由其他函数返回,即使我们没有定义它们,它们“本身”包含足够的信息,以便 Python 解释器可以对它们有意义地应用type() 和其他函数?

【问题讨论】:

    标签: python object memory import


    【解决方案1】:

    您错误地假设import 限制了加载到内存中的内容。 import 限制了名称绑定在你的模块全局变量中

    整个模块仍然加载,该模块的依赖项也是如此。仅仅因为你的命名空间没有绑定对datetime.timedelta对象的引用并不意味着它对datetime模块不可用。

    import statement documentation

    from 表单使用稍微复杂的过程:

    1. 找到from子句中指定的模块,必要时加载并初始化它;
    2. 对于import 子句中指定的每个标识符:
      1. 检查导入的模块是否具有该名称的属性
      2. 如果没有,请尝试导入具有该名称的子模块,然后再次检查导入的模块的该属性
      3. 如果未找到该属性,则引发ImportError
      4. 否则,对该值的引用存储在本地命名空间中,如果存在则使用 as 子句中的名称,否则使用属性名称

    因此,模块的加载和初始化是一个单独的步骤,每个模块执行一次。第二步绑定名称空间中的名称。

    from datetime import date 确保datetime 模块已加载,然后找到datetime.date 并将date = datetime.date 添加到您的 命名空间。

    如果您想查看加载了哪些模块,请查看sys.modules mapping。那是import statement machinery checks 用来查看给定模块是否已经加载的位置。

    【讨论】:

    • 谢谢! SE 仍然让我等 9 分钟,直到我可以接受你的回答 :) 但与此同时,为了好玩,让我问一下:是否有可能以某种方式诱使我的代码定义一个对象,将其存储在某个地方,然后加载它是由不同的 Python 脚本执行的,所以我实际上在运行时最终得到了一个对象,而我的 Python 脚本之前没有对其进行定义?
    • 类比为import datetimedate = datetime.datedel datetime
    • @Ayxan 啊,但后来我失去了对我的对象的引用。我希望仍然能够引用它,但是之前没有定义的对象,只是我内存中被占用的某个区域(我不确定我的要求是否有意义,我只是在尝试形式化我对 Python 解释器内部工作的模糊理解)。
    • @Ayxan: sorta-kinda-not-really,因为那必须假设名称 datetime 尚未绑定到其他东西。 date = __import__('datetime', fromlist=['date']).date 越来越近了。
    • @G.Anderson: 这是纯 Python 实现,在绝大多数安装中,所有这些名称都被 from _datetime import * 破坏,进一步向下加载 C-defined extension,其中 date_subtract()调用new_delta() 创建timedelta 实例。
    【解决方案2】:
    from datetime import date
    

    Date 正在某处导入 timedelta,因为它可能是一个依赖项,即使您没有看到它。

    【讨论】:

    • +1。您知道在我导入给定模块时是否有办法突出显示正在导入的所有依赖项?
    • @l7ll7:这比你想的要复杂得多。您可以对sys.modules 进行快照(这只会给您尚未加载 依赖项)或将bltins.__import__ 替换为跟踪正在导入的内容的包装函数(但这不会跟踪扩展模块加载更多模块)。
    • @MartijnPieters 哇,好的,我会把它留到以后的 SE 问题中,当我对 Python 有更多了解时......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-26
    • 2014-11-03
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多