【问题标题】:Python memory model for this program此程序的 Python 内存模型
【发布时间】:2014-05-01 13:09:35
【问题描述】:

当在http://pythontutor.com/ 上运行时,关于存储值和函数的符号,我的查询位于以下程序中。

我的问题是:

  1. python 执行模型如何在开始解释 python 程序之前在内存中查找上述程序?我如何可视化该内存布局?例如c可执行文件有代码/堆栈/堆/额外/数据段,仅作为示例,我不比较

  2. 'const' 是否是 32/64 位内存区域的名称,用于存储类型为整数的值 2?

  3. add()/sub()/other 函数显示在 Objects 列中,如图所示,那么,我如何看待存储为 Objects 的函数?我如何可视化它?

  4. 如图所示,op 是指向函数 sub() 的函数指针吗?

【问题讨论】:

  • 您询问的大部分细节对于 Python 编程应该完全忽略。 Python 不是根据内存或指针或类似的低级事物来定义的。 (实现需要担心这些东西,但您不必担心实现。)
  • @user2357112 对于您的声明“对于 Python 编程,您应该完全忽略”,人们无法避免来自 OOP 范式(如 Java)或命令式范式(如 C)的人提出的此类问题。正如 Noel 在下面所说的那样python 是动态和强类型的,因此理解应用于文字和函数的类型事物(在运行时)是有意义的。在我开始使用python 2-3 年后,我不知道 op 是函数指针还是某个类的引用变量,我觉得这不是学习语言的正确方法。
  • 我觉得,声明性范式语言(如 SQL)不鼓励用户学习内部细节。
  • 当你用 C 编程时,你会考虑内存和指针,因为这些东西是 C 的基础。除非你真的需要,否则你不会考虑哪个寄存器存储哪个变量或哪个您正在访问的缓存层。这些问题由实施为您处理。同样,在 Python 中,您会根据对象及其行为进行思考。您无需担心内存和指针,因为在 Python 级别,这些是实现细节。
  • 我去掉了Java标签,它与Java无关。它也与 C 无关,但我保留了该标签,因为您试图将 Python 的内存模型与 C 的内存模型进行比较。尽管如此,我还是给你的问题打了-1,因为尝试理解 Python 程序如何映射到 C 的内存模型是没有用的。相反,尝试学习如何用 C 编写 Python 解释器(例如,通过从 python.org 获取源代码)。

标签: python c object


【解决方案1】:
  1. 字典上的字典。字典是 Python 中排名第一的最重要的结构。

  2. 它是当前作用域字典中条目的键。值为对象2

  3. 并不是函数是对象,而是某些对象是函数。或数字。或字典。

  4. 它是当前作用域字典中条目的键。值为sub

【讨论】:

  • Ignacio,这两条语句的含义是什么:a)'值是对象 2' b)'一些对象是函数。或数字。或字典。'??---你如何在这里定义单词'object'?因为,在 OOP 世界中,对象具有状态和行为。
  • 为什么你认为 Python 中的对象没有状态和行为?
  • 我没有说,python 中的对象没有状态和行为,但是根据link 我理解,软件对象将其状态存储在字段中(某些编程语言中的变量)和通过方法(某些编程语言中的函数)暴露其行为。 ------但是在您的更新中,在第 2 点中,您说整数文字(2)是一个对象,在第 3 点中,您说函数 add()/sub() 是一个对象。
  • 那是因为他们是。
  • 其他一切都是对象。 >>> (2).__add__(3)5
【解决方案2】:
  1. 在 Python 中,不必太担心内存段和幕后发生的事情。相反,环境(范围)更重要。您包含的块和指针图是可视化内存的合理方法。白色部分显示了全球环境的样子。调用该函数时,会创建一个新的(蓝色)环境。

  2. const 是一个变量。 Python 中的变量是weakly 动态类型的,可以存储任何内容。其实Python integers don't overflow,可以存储超过264的数字。在这种情况下,const 是一个包含数字 2 的变量(名称容易混淆)。

  3. 函数是可调用代码块的抽象概念。您可以将其分配给变量,就像任何其他值一样。

  4. 1234563 Python 程序员只会说op 具有函数sub 作为值。

【讨论】:

  • “Python 中的变量是弱类型的” - 我会改写它。变量根本没有类型,但是值是有类型的(强类型)。
  • Python 不像 Perl 或 C 那样是弱类型的。它是动态,但类型。
  • @Kos 你的意思是,与语言无关,不应该说,变量是弱类型/强类型,因为它没有意义?我们需要说,值是弱/强类型的吗?
【解决方案3】:

每个 C(编译语言)程序在执行前都会在内存中加载代码/数据/堆栈/额外/堆段。在开始解释 python 程序之前,python 解释器是否为每个 python 程序创建任何内存布局?如果是,我如何可视化该内存布局?

它有一种布局,但这里堆是最重要的部分,因为每个对象都被放入堆中。代码段只是解释器,数据段也是解释器的内部状态,栈也是。

与 Python 程序相关的只是堆。但布局本身与任何其他程序一样。

const 是一个 32/64 位内存区域的名称,用于存储值 2,类型指定为整数?

它是当前工作空间中的一个名称,(这里:在模块的命名空间中),它本质上是一个在字符串和任意对象之间进行赋值的字典。在这种情况下,它使字符串const 指向一个包含值2 的整数对象。 (这个对象可以根据情况重新创建或重新使用;这没有区别,因为它是不可变的。)

add()/sub()/其他函数如图所示在对象列中,那么,我如何感知存储为对象的函数?如何将其可视化?

正如 my comments 写给 Ignacio 的回答:

在函数的情况下,您有一个具有某些字段的对象,其中包含 e。 G。字节码方面的代码,它具有的参数数量等。它甚至还有方法本身,例如__get__()在内部调用以将方法绑定到对象,或__call__()用于真正的函数调用,除了__format__()__repr__()

整数对象在内部深处有一个存储实际值的地方。在 Py2 中的 long() 或 Py3 中的任何 int() 的情况下,它存储数据以保存值(例如 2)以及它所需的长度。此外,它还有很多方法。看看dir(2) 的输出,看看它还有很多方法,比如格式化、for arithmetics 等。

如图所示,op 是指向函数sub() 的函数指针吗?

有点,是的。

有一个函数对象,它内部知道它的原始名称是sub。但是这个知识只是为了展示的目的。

在您的情况下,它是由两个名称引用的,opsub。所以引用它们中的任何一个都有相同的结果。

请注意,没有“函数指针”本身,只有引用或名称,它们指向任何类型的对象。对象的类型是固定的,但不是“引用的类型”(因为没有这样的东西)。

【讨论】:

  • glglgl 写你的第二点,我看到了一点,我认为,整数文字(2)被自动装箱为整数类(在运行时)并且 const 将是类型运行时的整数类。一般来说,任何字面量 "abc" , 3.2 在 'const = 2' 的赋值期间都会在运行时自动装箱到相应的类,因此 const 在运行时将是类型的整数类。
  • glglgl 写你的第三点,我不同意你的观点,我觉得一个函数(比如上面例子中的 sub() )也被包装在一个类中,然后由一个引用变量指向(比如 op in上面的示例),其中 op 将在运行时属于该类类型。对于第三点,我们也在 java 中这样做 'interface Sample { int sub(int x, int y); }' 或 'class Sample { int sub(int x, int y){return xy;} }' 所以我认为 const 是上面整数类的引用变量(在运行时)& op 是引用变量(不是函数sub() 封装到的类型类的指针)。
  • glglgl 当我在 python 中说引用变量时,我认为这个引用变量的行为与 java(在运行时)中的行为相同,除了在 java 中这个引用变量的类型在编译时是已知的(这是运行时的 X) 和 Y,例如 'X x = new Y();'其中 X 和 Y 是类 Y 是 X 的子级,x 是参考变量
  • 1.如果你来自 Java,也许你称之为自动装箱,我宁愿称之为“自动对象创建(和实习)”。但是const 只是引用int 的对象。 2. 是的,一般来说一切都是 Python 中的参考,但我看不出有什么矛盾。 (此外,一个函数可能“封装在一个类中”(绑定到它),但不是必须的。) 3. 这似乎是正确的。
  • glglgl 在上面的第 2 点中写下你的陈述:'此外,一个函数可以“包装在一个类中”(绑定到它),但不是必须的。'----- 如果你不包装成一个类,那么运行时引用变量op的类型是什么?
猜你喜欢
  • 1970-01-01
  • 2010-11-06
  • 1970-01-01
  • 1970-01-01
  • 2019-06-23
  • 1970-01-01
  • 2015-10-29
  • 1970-01-01
  • 2013-05-14
相关资源
最近更新 更多