如何在Python中模拟指针?( 四 )

如何在Python中模拟指针?
文章插图
 
在此示例中,您看到的代码几乎与以前相同,除了这次结果是True 。这是预实现对象的结果 。Python在内存中预先创建了某个对象子集,并将它们保存在全局命名空间中以供日常使用 。
哪些对象依赖于Python的预实现 。CPython 3.7预实现对象如下:
1.-5到256之间的整数
2.仅包含ASCII字母,数字或下划线的字符串
这背后的原因是这些变量很可能在许多程序中使用 。通过预先实现些对象,Python可以防止对一致使用的对象进行内存分配调用 。
预先实现小于20个字符且包含ASCII字母,数字或下划线的字符串 。背后的原因是假设这些字符串是某种身份:

如何在Python中模拟指针?

文章插图
 
在这里您可以看到s1和s2都指向相同的内存地址 。如果您要引入非ASCII字母,数字或下划线组成的字符串,那么您将得到不同的结果:
如何在Python中模拟指针?

文章插图
 
因为此示例中包含感叹号“!”,所以这些字符串不会被预先实现,并且s1和s2是内存中的不同对象 。
福利:如果您真的希望这些对象引用相同的内部对象,那么您可能需要查看sys.intern() 。文档中概述了此功能的一个用例:
预先实现的字符串对于在字典查找中获得一点性能很有用 - 如果字典中的键被预先实现,并且查找键被预先实现,则键比较(完成在散列之后)就可以通过指针来比较而不是用字符串来比较 。(来源)
预实现对象通常是混乱的来源 。请记住,如果您有任何疑问,可以随时使用id()和is确定对象是否相同 。
在Python中模拟指针仅仅因为Python中的指针本身不存在并不意味着你无法获得使用指针的好处 。实际上,可以有多种方法在Python中模拟指针 。您将在本节中学习到两种:
1.使用可变类型作为指针
2.使用自定义Python对象
好的,让我们进入正题 。
使用可变类型作为指针您已经了解过可变类型 。因为这些对象是可变的,所以您可以将它们视作指针,以此来模拟指针行为 。假设您复制了以下c代码:
如何在Python中模拟指针?

文章插图
 
此代码将一个指针指向一个整数(*x),然后将其值增加1 。这有一个运行代码的主函数:
如何在Python中模拟指针?

文章插图
 
在上面的代码中,将值2337赋给y,打印出当前值,将值增加1,然后打印出修改后的值 。执行此代码的输出如下:
如何在Python中模拟指针?

文章插图
 
在Python中模仿此类行为的一种方法是使用可变类型 。考虑使用列表并修改第一个元素:
如何在Python中模拟指针?

文章插图
 
在这里,add_one(x)访问第一个元素并将其值增加1 。通过使用列表,最终似乎已修改了该值 。那么Python中的指针确实存在吗?好吧,不 。唯一的可能是:因为列表是一种可变类型 。如果您尝试使用一个元组,则会收到错误消息:
如何在Python中模拟指针?

文章插图
 
上面的代码演示了元组是不可变的 。因此,它不支持项目赋值 。列表不是唯一可变的类型 。在Python中模仿指针的另一种常见方法是创建字典 。
假设您有一个应用程序,您希望每次发生有趣事件时都要跟踪 。实现此目的的另一种方法是创建一个字典 并使用其中的一项作为计数器:
如何在Python中模拟指针?

文章插图
 
在此示例中,counters字典用于跟踪函数调用的数量 。调用foo()函数后,计数器按预期增加到2 。这都是因为字典是可变类型 。
请记住,这只是模拟指针行为,并不直接映射到C或C ++中的真指针 。也就是说,这些操作在Python中会比在C或C ++中付出更多代价 。
使用Python对象使用字典是在Python中模拟指针的一种好方法,但有时您需要记住使用的密钥名称,这会很繁琐 。如果您在应用程序的各个部分都使用字典,则尤其如此 。这就是自定义Python类可以真正起到作用的地方 。
构建最后一个示例,假设您要跟踪应用程序中的指标 。创建一个类是解决那些讨厌的抽象细节的好方法:


推荐阅读