多年来我读了许多帖子,用#34解释Python变量; Python有名字,其他语言有变量"或者通过"对象和标签以及框#34;
我一直不喜欢这些解释,因为他们需要新的心理形象,并且在我看来,他们试图重新定义常用的术语。 (可以说Python也有变量,其他语言也有名字。)
由于我只使用Python进行了正确的编程,因此它的行为是我所知道的唯一一个,因此这些讨论对我影响不大。
尽管如此,在与其他人讨论之前,我想知道我对这个主题的理解是否正确:
在写这个问题时,我注意到之前已经问过similar question,并且该线程中的每个人,包括OP,都认为Python变量是而不是指针(相反,答案使用上面的解释代替),因为
i = 5
j = i
j = 3
print(i)
结果为5
。但是,对我来说,这个结果非常有意义。根据我的理解,它被翻译为
void *i;
void *j;
int temp1 = 5; %RHS of line 1 above
i = &temp1; %LHS of line 1 above
j = &i; %Line 2 above
int temp2 = 3; %RHS of line 3 above
j = &temp2; %LHS of line 3 above
(确切地说,前面提到的问题有一个答案可以提供或多或少的解释,但是得分为负,而且没有任何关于它有什么问题的评论。)
据我所知,这个模型也完美地解释了Python中的参数,例如,它解释了为什么
def foo(b):
b=2
a=1
foo(a)
print(a)
结果为1
。在foo
内,本地指针变量b
被重定向到新整数对象的地址。外部指针变量a
仍然指向值为1
的整数对象。
为了获得完整的图片,理解属性访问以及为什么可以使用它来更改传递给函数的变量,我会添加声明:
Python中使用.
进行的属性访问转换为C ++中的->
由于索引只是语法糖,因此它也适用于此规则。
总之,我相信两个简单的规则解释了Python中变量的一切。这是一个大胆的陈述,我很高兴知道以及是错误的。
编辑:Another very popular question其答案反对指针类比
答案 0 :(得分:0)
有点(好吧,很多)比那时更复杂。但是,简单地说,是的每个python对象都是指向object.c
中定义的PyObject
或PyVarObject
的指针
/* Nothing is actually declared to be a PyObject, but every pointer to
* a Python object can be cast to a PyObject*. This is inheritance built
* by hand. Similarly every pointer to a variable-size Python object can,
* in addition, be cast to PyVarObject*.
*/
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
typedef struct {
PyObject ob_base;
Py_ssize_t ob_size; /* Number of items in variable part */
} PyVarObject;
答案 1 :(得分:0)
正确的解释是: Python有名字,其他语言有变量。这意味着Python的变量是通过在运行时在字典中查找其名称来恢复的。
虽然,我会在我早期的Python时代告诉你,我也发现这个解释令人失望。我当时所喜欢的将是这对开发者意味着什么的例子。
dict
在低级语言中,变量的名称被抛弃,并由编译器在内存中的地址替换。在Python中不是这种情况,它允许您使用vars
内置函数访问所有变量,返回范围变量的字典。
这意味着您可以从该词典中读取变量。
foo = 1
vars()['foo'] # 1
并且您可以使用此dict更新甚至声明变量。
vars()['bar'] = 1
bar # 1
这也意味着您可以列出范围内的所有变量。
foo = 1
bar = 1
vars().keys() # ['__name__', '__doc__', ... , 'foo', 'bar'])
NameError
例外在C中,访问尚未声明的变量是编译错误。在Python中,因为变量'在dict中查找名称,它是一个运行时异常,可以像任何异常一样被捕获。
try:
print(foo)
except NameError:
print('foo does not exist') # This is printed
在Python中,通过它在内存中的位置访问值的整个机制对您来说是隐藏的。您访问变量的方法是了解其名称。
特别是这意味着您可以删除名称并阻止对其值的任何访问。
foo = object()
del foo
# The above object is now completely out of reach
以上操作是删除'foo'
词典中的vars()
键。