在Python中,所有变量都是void指针吗?

时间:2018-05-09 12:45:37

标签: python variables parameters

多年来我读了许多帖子,用#34解释Python变量; Python有名字,其他语言有变量"或者通过"对象和标签以及框#34;

我一直不喜欢这些解释,因为他们需要新的心理形象,并且在我看来,他们试图重新定义常用的术语。 (可以说Python也有变量,其他语言也有名字。)

由于我只使用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其答案反对指针类比

2 个答案:

答案 0 :(得分:0)

有点(好吧,很多)比那时更复杂。但是,简单地说,是的每个python对象都是指向object.c

中定义的PyObjectPyVarObject的指针
/* 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()键。