Python内存模型和指针

2024-01-08

我正在学习 Python,并对 Python 的内存模型感到困惑

变量包含它所引用的对象的内存地址

这听起来就像 Python 变量实际上是指针,因为它们只直接包含实际对象实例的内存地址。

那么当我调用变量名时Python会做什么呢? Python是否总是自动搜索包含的内存地址并使用存储在那里的对象?

例如,看下面的代码和注释,我对流程的理解是否正确?

a=500 # create an int object with value 500, stored this object at a memory address, let's call it id1
b=a #trying to assign a to b, value of a is actually id1, memory address to object int(500), 
# but Python automatically return the object rather than the memory address stored at a. 
# Then refer b to this obejct by storing the same memory address at b 
a=501 # create an  new int object with value 500, stored this object at a new memory address id2, refer a to this new int(500) by storing id2 at a
print(b) # value of b is still id1 and refer to the first int(500) object

回答你的询问:“那为什么a=100;b=a;a=101不会改变 b 的值”,我提醒你,即使在 C 中,情况也不会如此。事实是a and b是指针,并且相等,并不意味着更改为a影响b。他们不是别名。*a and *b可能是,但不是a and b.

在 C 语言中,常量字符串非常相似。

char *a="hello";
char *b=a;
a="foo";
printf("%s\n", b);
// prints hello

是的,a和b是指针。但它仍然是a当你打字时你会改变a="foo";,而不是其内容。所以,是的,a and b我们是平等的……直到,你说a="foo";当他们不再相等时,因为你改变了a。它们只是指针。毕竟这是一个类似于另一个的值。看到这一点并不陌生a and b在此代码中不再等于它应在的代码中

int a=12;
int b=a;
a=15;

他们本来是平等的,后来却不平等了。指针只是值。地址。

可以共享的正是该地址中的内容。这并不奇怪。

int T[10]={1,2,3,4,5,6,7,8,9,10};
int *a=&(T[2]);
int *b=a;
printf("%d %d\n", *a, *b);
// prints 3 3
*a=5;
printf("%d %d\n", *a, *b);
// prints 5 5

您可能想知道为什么我需要整个数组。好吧,这只是为了向您展示指针的这种“别名”行为只不过是这个看似不那么神奇的例子

int T[10]={1,2,3,4,5,6,7,8,9,10};
int ia=2;
int ib=a;
printf("%d %d\n", T[ia], T[ia]);
// prints 3 3
T[ia]=5;
printf("%d %d\n", T[ia], T[ib]);
// prints 5 5

指针就是这样。指数。除了它们是所有内存的全局大数组中的索引形式之外。但“别名”并没有什么神奇之处*a and *b,事实上这种“别名”行为影响*a and *b, 但不是a and b(改变a不会改变b)。只要ia and ib在我的最后一个示例中没有改变并且保持相等,之间存在别名T[ia] and T[ib](显然,你会说,他们都是T[2]。嗯,是的,“显然”,但只不过是指针),并且之间没有“别名”ia and ib; ia=5,不会影响价值T[ib]。再说一次,是的,“显然”,但并不比改变更明显a不改变 的值*b.

现在,回到Python:是的,变量包含指向对象的指针,而不是对象本身。但是,如果你改变 a,你就会改变指针。

a=[1,2,3,4]
b=a
print(a[1],b[1]) # prints 2 2
a[1]=5
print(a[1],b[1]) # prints 5 5

之间存在“别名”a[?] and b[?]因为我们说过b=a. But

a=[1,2,3,4]
b=a
a=[0,2,3,4]
print(a[0], b[0]) # prints 0 1

a 和 b 之间没有“别名”

但是,你可能会问,那么,我怎样才能改变 a 的内容,而不改变a本身(指针)。

好吧,我们刚刚做到了。没有*python 中的运算符(嗯,有一个,字面意思是*,但这与此事无关)。因此,如果a and b是一个内容可以修改的对象(就像我们刚才所做的列表。或者字典。或者类的实例。或者库提供的一些特定对象,例如 ndarray 或 pandas dataframes),只要a=b,并且你不改变的值a and b,当您更改其中之一的内容时(a[1]=12 or a['bla']='foo' or a.foo=15,或者...)它影响另一个的内容(显然:它们是同一个对象)

但并非所有对象都是可修改的。

a=12
b=a
# The is no `a.value=15` that would change a values, without changing the object

这些是不可变的对象。为什么我在 C 中使用常量字符串类比

char *a="hello";
char *b=a;
a="foo"; // Doesn't change b

因为,同样,它们也可能是对象。但您无法更改其内容。你不能strcpy(a,"bar"),因为它们是常量字符串。所以,如果你想改变a您必须更改指针,而不是内容。

对于不可变对象也是一样的

a=12
b=a
# Only way to change a value is to change a
a=13

所以,从字面上看12不是一个值,而是一个指向实例的指针int(这是一个思维模型,而不是现实)。当然a不知何故是一个指针。但唯一的说法是a不再“指向”其值为的 int12,但现在指向一个 int,其值为13,并不是要改变所指向的内容a,因为它是不可变的,但要改变a,并使其“指向”另一个对象,其值为13

同样(对于习惯几乎所有其他语言的人来说更令人惊讶)

a="hello"
b=a
a[0]='H' # wouldn't work

行不通。字符串是不可变的。获得资本 H 的唯一方法是

a="hello"
b=a
a="Hello"

但当然,这并不影响b.

元组也是如此:a=(1,2); b=a你不能a[0]=3, 你必须a=(3,2)这不影响b

因此,您可以将所有变量视为指针。但没有& and *操作员。没有显式引用、取消引用运算符。只是,如果a=b、 和 是可变的,那么 a 的内容与 b 的内容相同,即使您更改a的内容(通过说a[...]=...例如)。而如果a=b但都是不可变的,那么,内容a与内容相同b,但这并不重要,因为你无法更改的内容a, only a本身,通过说a=...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python内存模型和指针 的相关文章

随机推荐

  • 蒙皮网格着色器的统一顶点位移(动画轮廓,Three.js)

    我想我已经解决了在 Three js 中渲染网格上的边框 轮廓的实现 这是许多游戏用于突出显示对象 角色的技术 Diablo 1 and 3 for example 这是详细信息 https stackoverflow com questi
  • 您不知道已安装发电机

    我刚刚安装了 Yeoman 和一些发电机 然而 由于 usr lib文件夹受到保护 我选择更改 NPM 安装其软件包的位置的前缀 现在 一切都在安装 node 我也改变了我的 PATH并添加了 node bin 但是 当我执行yo
  • 更改 JTextArea 中特定行的字体

    您好 我正在开发一个聊天应用程序 我希望用户可以更改他 她正在编写的字体 有一个setFont 函数 但它更改了 TextArea 中所有字符串的字体 所以我只想更改我的字体 如果您能帮助我 我将不胜感激 那么我想我必须学一点 HTML 我
  • 以编程方式创建Windows用户c#.net(使用PricinpalUser / CreateProfile)

    简而言之 我想做的是创建一个能够登录的新用户 我从各种来源提取了代码 并尝试简化它 然而 我遇到了一些绊脚石 当我打电话时UserPrincipal Save 它给了我一个错误 在缓存中找不到目录属性 异常类型 COMExceptioncr
  • 在 Visual Studio 设计器中隐藏 WPF 元素

    我有一个 WPF 表单 基本上如下所示
  • 如何设置 Android 操作栏上菜单项的样式

    关于操作栏样式的问题有很多 但我发现的问题要么与选项卡样式有关 要么有不适合我的答案 问题其实很简单 我希望能够更改操作栏中菜单项的文本样式 甚至只是颜色 我读过这个 还有这个问题 Android Honeycomb 中的操作栏样式 htt
  • 如何使用机器人框架和 selenium 读取 Web 控制台输出?

    我正在尝试读取网页的控制台输出 特别是我需要使用 RF 和 Selenium 进行 POST GET PUT ajax 调用 我在网上找到了一些帮助 但似乎无法使其发挥作用 我的Python脚本是 from selenium webdriv
  • 如何动态设置 EditText 高度

    我想简单地将 EditText 组件的高度设置为用户屏幕高度的 50 我正在从 xml 文件 main xml 创建初始布局 该文件加载到 Activity 的 onCreate Bundle 中 从 xml 配置中 我了解如何将 Edit
  • IronPython Web 框架

    Python 似乎有很多优秀的 Web 框架 有人在 IronPython 中使用过这些 Pylons Web2Py Django 吗 Django 已在 IronPython 上运行 http unbracketed org 2008 m
  • 依赖类型:依赖对类型与不相交联合有何相似之处?

    我一直在研究依赖类型 我了解以下内容 Why 通用量化 https en wikipedia org wiki Universal quantification被表示为依赖函数类型 x A B x means 对全部x类型的A有一个类型的值
  • C# Windows 窗体用户控件控件设计器支持

    我正在寻找的是对用户控件内的控件的相同类型的设计器支持 即 调整用户控件内的文本框大小 移动标签将用户控件放置到表单上之后 我能做的事 创建一个用户控件 使用设计器向其添加控件 创建一个新的窗口窗体应用程序 将用户控件添加到工具箱 将控件拖
  • JQuery 在该位置插入表格行

    我一直在研究一种能够向 html 表插入行的解决方案 这非常棘手 我发现了一些有用的东西 但仅适用于第一个 插入 我不知道我做错了什么 我有一个包含 3 列的基本表格 每个表格都有一个按钮 允许在两行之间插入一行 我在这个网站上搜索了一个解
  • 如何让 .env 预提交 + mypy + django-stubs

    我尝试在提交之前配置启动 mypy django stubs 检查 我使用预提交 当我尝试提交时 出现错误django core exceptions ImproperlyConfigured 设置 POSTGRES DB 环境变量 该变量
  • java.sql 中的日期时间等效项? (有 java.sql.datetime 吗?)

    到目前为止 我还没有找到明确的答案 我想知道使用PreparedStatement 的SQL 类型DATETIME 和java 类型的等价物是什么 我已经发现 http www java2s com Code Java Database S
  • Shell 脚本中的 exec ${PERL-perl} -Sx $0 ${1+"$@"} 是什么意思?

    我的任务是将包含 Shell 脚本 Perl 代码的 shell 脚本转换为 Python 我设法将 Perl 代码转换为 Python 但是有这个shell脚本语句我不明白 usr bin sh exec PERL perl Sx 0 1
  • 没有元素时流的特殊行为

    我如何用 java 8 Streams API 表达这一点 我想表演itemConsumer对于流的每个项目 如果有 没有我想要执行的项目emptyAction 当然我可以写这样的东西 Consumer itemConsumer Syste
  • 没有画布的 HTML5 getImageData [重复]

    这个问题在这里已经有答案了 有没有办法在没有画布的情况下使用图像的 getImageData 我想要获取图像鼠标位置处的像素颜色 不 你不能 但是获取 imageData 可以使用内存中的画布来完成 这既快速又简单 var canvas d
  • Powershell ISE 在使用 GitLab Runner 时抛出 RemoteException

    I am trying to stop GitlabRunner windows service using powershell When I execute the command in elevated powershell prom
  • 如何使用可视化代码编辑器在 chrome 上运行 flutter

    如何在 Chrome 上运行 flutter 应用程序 我已经安装了颤振套件并运行 颤振通道测试版 颤振升级 并在 Visual Studio Code 上安装扩展 就像与flutter mobile create flutter laun
  • Python内存模型和指针

    我正在学习 Python 并对 Python 的内存模型感到困惑 变量包含它所引用的对象的内存地址 这听起来就像 Python 变量实际上是指针 因为它们只直接包含实际对象实例的内存地址 那么当我调用变量名时Python会做什么呢 Pyth