Python中的命名查询

4
当我说,
>>>radius = 2

在内部,会在__main__模块的全局框架中创建一个名为radius的新对象,该对象是int类的。还将通过名称radius创建引用变量,指向该对象。当我说:
>>>from math import sqrt

在内部,名为sqrt的新对象在__main__模块的全局框架中创建,该对象是function类的。还通过名称sqrt创建引用变量,该变量指向function类型的对象。
当我说,
>>>def square(x):
         return mul(x,x)

在内部,一个名为square的新对象在__main__模块的全局框架中被创建,这个对象是类function的。还创建了名为square的引用变量,它指向那个function类型的对象。
我的问题:
我的理解正确吗?
或者 radiussqrtsquare对象是在__main__模块的全局框架之外创建的,而引用变量(radius sqrt square)位于__main__模块的全局框架中,指向这些对象吗?
在CS61A Fall 2012课程中,老师说,这就是它的工作方式,看起来隐藏了Python程序内存模型的许多细节。 program environment in memory

2
对象没有名称,它们只有引用。因此,说“通过名称radius创建了一个新对象”是错误的。阅读:关于名称和对象的一点说明 - Ashwini Chaudhary
不。这只是创建了一个名为“radius”的名称(而不是对象),该名称引用与字面量“2”引用相同的int对象。 - chepner
1
@200OK:我认为称它们为名称比称它们为引用更好。因为具有不可变类型的变量绝对不是引用。 - Neil G
@NeilG 那么,在Python中我们什么时候考虑引用?我的意思是指指向模块/函数/类()对象的变量也是Names吗?而不是references - overexchange
@NeilG 我猜,按名称传递参数和按值传递参数是一样的,会创建存储的另一个副本并为其分配新名称。 - overexchange
显示剩余9条评论
2个回答

2

询问一个对象是在哪里创建的与引用存在的位置有点无意义。正如200 OK在评论中指出的那样,所有对象名称都是引用——没有一个名称比其他名称更加规范或本地化。对象只是存在(在私有堆上,尽管这对于所有目的来说都是不相关的),而名称指向它们。

话虽如此,你的问题中有一个细微之处并不完全正确。当你从一个模块中导入东西——无论是整个模块本身还是仅仅一个函数——该模块的引用被存储在sys.modules字典中。这确保了当代码的另一部分从该模块中导入时,它不会被重新导入;使用现有的已导入版本。


为什么称它们为引用?如果你说 a = 2 然后 b = a,并不是说 b 是对 a 的引用,也不是对同一对象的引用,因为 a += 2b 没有影响。难道把它们称为名称不是更好吗?同一对象有两个名称。 - Neil G
我不理解sys.modules字典(picturize),因此我无法想象任何简单的Python程序在内存中的样子,并且当我们尝试指向其他模块/函数时会指向哪些。您能否制作一个图表,展示任何指向不同模块的样本(简单)Python程序(在我的问题上下文中)?那将使我的生活更简单。 - overexchange
@DanielRoseman,如果我的程序由多个.py文件组成,那么您不认为我需要像我上面提到的那样进行可视化处理吗? - overexchange
不,绝对不是。你只需要导入东西并使用它即可。Python如何分配内存不是你的责任。它甚至可能在不同的Python版本之间发生变化,但你不应该关心这些。 - Daniel Roseman
1
@overexchange:没错,就像我的第一条评论一样... - Neil G
显示剩余11条评论

0
__main__模块的全局框架中,内部创建了一个名为radius的新对象,该对象是int类的对象。
您正在混淆对象创建和绑定(分配)对对象的引用。语句radius = 2会导致:
  • 评估表达式2,这可能会创建或不创建对象(在CPython中不会因为小整数被缓存),然后
  • 将名称radius绑定到评估产生的对象(值)。
同样,在import的情况下,import可能会创建或不创建对象。如果之前已经导入了math,则其对象已经被创建。您只是将一个新名称sqrt分配给由导入math模块创建的对象。询问对象是否驻留在模块中没有意义,因为对象不驻留在模块中。它们可以被模块引用或通过导入创建,但之后,它们只存在于一个大而平的堆空间中。它们的引用形成了一个结构化的命名空间。

def 是特殊的,因为它既会对一个函数对象进行求值,又会将一个名称绑定到该函数对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接