Python 为什么我们可以使用变量名来获取存储在其中的数据?
在使用Python时,我遇到了一个长期困扰我的问题。比如说,我使用numpy定义一个数组Python 为什么我们可以使用变量名来获取存储在其中的数据?,python,arrays,numpy,Python,Arrays,Numpy,在使用Python时,我遇到了一个长期困扰我的问题。比如说,我使用numpy定义一个数组x=np.array([1,2]) 我认为,这意味着x是classarray的一个实例。此外,本教程还指出,[1,2]实际上存储在x.data中。但是,我通过实例名称x而不是Python中的x.data获得数据 这是怎么发生的?实例名称x和x.data之间存在链接 x和x.data是不同的类型,尽管它们在解释内存中相同位置的数据 In [1]: import numpy as np In [2]: x =
x=np.array([1,2])
我认为,这意味着x
是classarray
的一个实例。此外,本教程还指出,[1,2]
实际上存储在x.data
中。但是,我通过实例名称x
而不是Python中的x.data
获得数据
这是怎么发生的?实例名称
x
和x.data
之间存在链接 x
和x.data
是不同的类型,尽管它们在解释内存中相同位置的数据
In [1]: import numpy as np
In [2]: x = np.array([1,2])
In [3]: type(x)
Out[3]: numpy.ndarray
In [4]: type(x.data)
Out[4]: buffer
x.data
是指向组成内存中数组对象的底层字节缓冲区的指针,在中引用
当我们检查底层数据类型(dtype
)时,数组正在存储数据,如下所示:
In [5]: x.dtype
Out[5]: dtype('int64')
int64
由64位或8个字节(一个字节中有8位)组成。这意味着x
的底层缓冲区,x.data
应该是长度为16的缓冲区。我们在此确认:
In [6]: len(x.data)
Out[6]: 16
最后,我们可以查看缓冲区的实际值,以了解Python如何将值存储在内存中:
In [7]: for i in range(len(x.data)): print ord(x.data[i])
1
0
0
0
0
0
0
0
# first 8 bytes above, second 8 below
2
0
0
0
0
0
0
0
我们使用返回字节的值,因为numpy
将值存储为8位(1字节)字符串
由于每个字节仅存储8位信息,因此循环打印的上述值都不会超过255
x
和x.data
之间的链接是x.data
指向您在检查x
时看到的值在内存中的位置numpy
使用ndarray
类型作为内存中较低级别存储之上的抽象,以便于在较高级别处理数组,例如在索引1处获取x
的值:
In [8]: x[1]
Out[8]: 2
不需要自己实现正确的偏移和二进制到整数的转换。x
和x.data
是不同的类型,尽管它们在解释内存中相同位置的数据
In [1]: import numpy as np
In [2]: x = np.array([1,2])
In [3]: type(x)
Out[3]: numpy.ndarray
In [4]: type(x.data)
Out[4]: buffer
x.data
是指向组成内存中数组对象的底层字节缓冲区的指针,在中引用
当我们检查底层数据类型(dtype
)时,数组正在存储数据,如下所示:
In [5]: x.dtype
Out[5]: dtype('int64')
int64
由64位或8个字节(一个字节中有8位)组成。这意味着x
的底层缓冲区,x.data
应该是长度为16的缓冲区。我们在此确认:
In [6]: len(x.data)
Out[6]: 16
最后,我们可以查看缓冲区的实际值,以了解Python如何将值存储在内存中:
In [7]: for i in range(len(x.data)): print ord(x.data[i])
1
0
0
0
0
0
0
0
# first 8 bytes above, second 8 below
2
0
0
0
0
0
0
0
我们使用返回字节的值,因为numpy
将值存储为8位(1字节)字符串
由于每个字节仅存储8位信息,因此循环打印的上述值都不会超过255
x
和x.data
之间的链接是x.data
指向您在检查x
时看到的值在内存中的位置numpy
使用ndarray
类型作为内存中较低级别存储之上的抽象,以便于在较高级别处理数组,例如在索引1处获取x
的值:
In [8]: x[1]
Out[8]: 2
而不需要自己实现正确的偏移和二进制到整数的转换。非常好的答案。我很感激他们。但是关于实例名“x”和x的属性x.data之间的联系的解释仍然让我感到困惑。也许,我应该再举一个让我困惑的例子,如下所示。我使用pytorch定义一个变量x,计算并得到它的梯度x.grad,意思是grad是实例x的一个属性。但是,我们可以使用x.grad.data.zero_u2;()将x.grad设置为零,这意味着data.zero_2;()是x.grad的方法。为什么属性有一个方法?非常感谢。x
只是一个python类
,因此它可以在其上定义任意属性,可以包括其他类、函数和值,包括变异并使用存储在类本身中的值的函数。如果您想知道data
属性实际上是如何在ndarray
type对象上定义的,那么在Python中的OOP上可能会有所帮助,这是非常有用的答案。我很感激他们。但是关于实例名“x”和x的属性x.data之间的联系的解释仍然让我感到困惑。也许,我应该再举一个让我困惑的例子,如下所示。我使用pytorch定义一个变量x,计算并得到它的梯度x.grad,意思是grad是实例x的一个属性。但是,我们可以使用x.grad.data.zero_u2;()将x.grad设置为零,这意味着data.zero_2;()是x.grad的方法。为什么属性有一个方法?非常感谢。x
只是一个python类
,因此它可以在其上定义任意属性,可以包括其他类、函数和值,包括变异并使用存储在类本身中的值的函数。如果您想知道data
属性实际上是如何在ndarray
type对象上定义的,那么在Python中的OOP上可能会有所帮助,这真的很有帮助