似乎2 is 2和3 is 3在python中始终为true,通常,对整数的任何引用都与对相同整数的任何其他引用相同。 None(即None is None)也是如此。我知道用户定义类型或可变类型不会发生这种情况。但是有时它在不可变类型上也会失败:

>>> () is ()

True

>>> (2,) is (2,)

False

即:空元组的两个独立构造在内存中产生对同一对象的引用,但是相同的一个(不可变)元组的两个独立构造最终创建了两个相同的对象。我进行了测试,frozenset的工作方式类似于元组。

由什么决定一个对象是要在内存中重复还是要有一个包含大量引用的实例?在某种意义上,它是否取决于物体是否是“原子的”?它会根据实施情况而变化吗?

参考方案

Python具有某些类型,可以保证只有一个实例。这些实例的示例是None,NotImplemented和Ellipsis。这些是(按定义)单例,因此像None is None之类的东西一定会返回True,因为无法创建新的NoneType实例。

它还提供了一些doubletons 1 True和False 2-对True的所有引用都指向同一对象。同样,这是因为无法创建bool的新实例。

python语言保证了以上所有内容。但是,您已经注意到,有些类型(全部不可变)存储一些实例以供重用。该语言允许这样做,但是不同的实现可以选择是否使用此配额-取决于其优化策略。属于此类的一些示例是小整数(-5-> 255),空tuple和空frozenset。

最后,Cpython intern在解析过程中某些不可变的对象...

例如如果您使用Cpython运行以下脚本,则会看到它返回True:

def foo():

return (2,)

if __name__ == '__main__':

print foo() is foo()

这似乎真的很奇怪。 Cpython正在玩的技巧是,每当构造函数foo时,它就会看到包含其他简单(不可变)文字的元组文字。 python不会一遍又一遍地创建此元组(或其等效项),而只是创建一次。因为整个交易是不可变的,所以没有更改该对象的危险。一遍又一遍地调用相同的紧密循环,这对于性能而言可能是一个巨大的胜利。小绳子也会被扣留。真正的胜利在于字典查找。 Python可以执行(非常快的)指针比较,然后在检查哈希冲突时退回到较慢的字符串比较。由于大量的python建立在字典查找上,因此对于整个语言来说,这可能是一个很大的优化。

1我可能只是编造了这个词...但希望您能理解...

2在正常情况下,您无需检查对象是否是对True的引用-通常,您只需关心对象是否“真实”即可,例如如果if some_instance: ...将执行分支。但是,我将其放在此处只是为了完整性。

注意is可用于比较不是单例的事物。一种常见用法是创建一个哨兵值:

sentinel = object()

item = next(iterable, sentinel)

if items is sentinel:

# iterable exhausted.

要么:

_sentinel = object()

def function(a, b, none_is_ok_value_here=_sentinel):

if none_is_ok_value_here is sentinel:

# Treat the function as if `none_is_ok_value_here` was not provided.

这个故事的寓意是总是说出您的意思。如果要检查一个值是否是另一个值,请使用is运算符。如果要检查一个值是否等于另一个值(但可能不同),请使用==。有关is和==(以及何时使用)的区别的更多详细信息,请参阅以下文章之一:

Is there a difference between `==` and `is` in Python?

Python None comparison: should I use "is" or ==?

附录

我们已经讨论了这些CPython实现细节,并声称它们是优化。最好只是衡量我们从所有优化中得到的收益(使用is运算符时会产生一些混乱)。

字符串“interning”和字典查找。

这是一个小脚本,您可以运行该脚本来查看如果使用相同的字符串而不是其他字符串来查找值,则字典查找的速度将提高多少。请注意,我在变量名称中使用了术语“interned”-这些值不一定是intern(尽管可以)。我只是用它来表示“interned”字符串是字典中的字符串。

import timeit

interned = 'foo'

not_interned = (interned + ' ').strip()

assert interned is not not_interned

d = {interned: 'bar'}

print('Timings for short strings')

number = 100000000

print(timeit.timeit(

'd[interned]',

setup='from __main__ import interned, d',

number=number))

print(timeit.timeit(

'd[not_interned]',

setup='from __main__ import not_interned, d',

number=number))

####################################################

interned_long = interned * 100

not_interned_long = (interned_long + ' ').strip()

d[interned_long] = 'baz'

assert interned_long is not not_interned_long

print('Timings for long strings')

print(timeit.timeit(

'd[interned_long]',

setup='from __main__ import interned_long, d',

number=number))

print(timeit.timeit(

'd[not_interned_long]',

setup='from __main__ import not_interned_long, d',

number=number))

此处的确切值并不太重要,但是在我的计算机上,短字符串显示的速度大约是7分之一。长字符串的速度快将近2倍(因为如果要比较的字符串更多,则字符串比较会花费更长的时间)。差异在python3.x上并没有那么明显,但仍然肯定存在。

元组“实习”

这是一个您可以使用的小脚本:

import timeit

def foo_tuple():

return (2, 3, 4)

def foo_list():

return [2, 3, 4]

assert foo_tuple() is foo_tuple()

number = 10000000

t_interned_tuple = timeit.timeit('foo_tuple()', setup='from __main__ import foo_tuple', number=number)

t_list = (timeit.timeit('foo_list()', setup='from __main__ import foo_list', number=number))

print(t_interned_tuple)

print(t_list)

print(t_interned_tuple / t_list)

print('*' * 80)

def tuple_creation(x):

return (x,)

def list_creation(x):

return [x]

t_create_tuple = timeit.timeit('tuple_creation(2)', setup='from __main__ import tuple_creation', number=number)

t_create_list = timeit.timeit('list_creation(2)', setup='from __main__ import list_creation', number=number)

print(t_create_tuple)

print(t_create_list)

print(t_create_tuple / t_create_list)

这对时间来说有点棘手(我很高兴提出任何更好的想法以在评论中对时间进行计时)。要点是,平均而言(和在我的计算机上),创建一个元组所花费的时间大约是列表所花费的时间的60%。但是,foo_tuple()平均花费foo_list()花费时间的40%。这表明我们确实从这些实习生那里获得了一点提速。随着元组变大,节省的时间似乎增加了(创建更长的列表需要更长的时间-元组“创建”自创建以来就花费固定的时间)。

另请注意,我称此为“实习生”。实际上不是(至少在相同的意义上,字符串是固定的)。我们可以看到这个简单脚本的区别:

def foo_tuple():

return (2,)

def bar_tuple():

return (2,)

def foo_string():

return 'foo'

def bar_string():

return 'foo'

print(foo_tuple() is foo_tuple()) # True

print(foo_tuple() is bar_tuple()) # False

print(foo_string() is bar_string()) # True

我们看到字符串确实是“interned”的-使用相同文字表示法的不同调用将返回相同的对象。元组“实习”似乎特定于一行。

为什么使用'=='或'is'比较字符串有时会产生不同的结果? - python

我有一个Python程序,其中将两个变量设置为'public'值。在条件表达式中,我有比较var1 is var2失败,但如果将其更改为var1 == var2,它将返回True。现在,如果我打开Python解释器并进行相同的“是”比较,则此操作成功。>>> s1 = 'public' >&gt…单行的'if'/'for'语句是否使用Python样式好? - python

我经常在这里看到某人的代码,看起来像是“单线”,这是一条单行语句,以传统的“if”语句或“for”循环的标准方式执行。我在Google周围搜索,无法真正找到可以执行的搜索类型?任何人都可以提出建议并最好举一些例子吗?例如,我可以一行执行此操作吗?example = "example" if "exam" in exam…在返回'Response'(Python)中传递多个参数 - python

我在Angular工作,正在使用Http请求和响应。是否可以在“响应”中发送多个参数。角度文件:this.http.get("api/agent/applicationaware").subscribe((data:any)... python文件:def get(request): ... return Response(seriali…python JSON对象必须是str,bytes或bytearray,而不是'dict - python

在Python 3中,要加载以前保存的json,如下所示:json.dumps(dictionary)输出是这样的{"('Hello',)": 6, "('Hi',)": 5}当我使用json.loads({"('Hello',)": 6,…Python exchangelib在子文件夹中读取邮件 - python

我想从Outlook邮箱的子文件夹中读取邮件。Inbox ├──myfolder 我可以使用account.inbox.all()阅读收件箱,但我想阅读myfolder中的邮件我尝试了此页面folder部分中的内容,但无法正确完成https://pypi.python.org/pypi/exchangelib/ 参考方案 您需要首先掌握Folder的myfo…

python中类似对象吗_在Python中,两个对象什么时候相同? - python相关推荐

  1. python改变列的数据类型_更改Pandas中列的数据类型

    在熊猫中,你有三种主要的转换类型的选择:astype()-将(几乎)任何类型转换为(几乎)任何其他类型(即使这样做不一定明智).还允许您转换为范畴类型(非常有用). infer_objects()-一 ...

  2. python去除图片复杂背景_[OpenCV-Python] OpenCV 中的图像处理 部分 IV (五)

    部分 IV OpenCV 中的图像处理 22 直方图 22.1 直方图的计算,绘制与分析 目标 • 使用 OpenCV 或 Numpy 函数计算直方图 • 使用 Opencv 或者 Matplotli ...

  3. python线上编辑问题_大型线上项目中动态语言诸多问题之二 -- 以 Python 语言为例...

    第一个问题:Mutable对象被误改 这个是在线上环境出现过的一个BUG 事后说起来很简单,服务端数据(放在dict里面的)被意外修改了,但查证的时候也花了许多时间,伪代码如下: def routin ...

  4. 下列变量名不符合python命名规范的是_下列选项中不符合Python语言变量命名规则的是...

    [单选题]下列Python保留字中,不用于表示分支结构的是 [单选题]以下程序的输出结果是: j = '' for i in "12345": j += i + ',' print ...

  5. python中digits什么意思_在Caffe中使用 DIGITS自定义Python层

    Caffe 使得我们有了使用Python自定义层的能力,而不是通常的C++/CUDA.这是一个非常有用的特性,但它的文档记录不足,难以正确实现本演练将向您展示如何使用DIGHT来学习实现Python层 ...

  6. python如何安装panda数据库_在Pycharm中安装Pandas库方法(简单易懂)

    开发环境的搭建是一件入门比较头疼的事情,在上期的文稿基础上,增加一项Anaconda的安装介绍.Anaconda是Python的一个发行版本,安装好了Anaconda就相当于安装好了Python,并且 ...

  7. python如何打印txt文件_关于文本:如何将所有打印导出到Python中的.txt文件?

    本问题已经有最佳答案,请猛点这里访问. Possible Duplicate: Redirect stdout to a file in Python? 我终于完成了我项目的所有代码.现在,我需要所有 ...

  8. is在python中是什么意思_【IT专家】关键字:is和=在python中有什么区别

    本文由我司收集整编,推荐下载,如有疑问,请与我司联系 关键字: is 和 = 在 python 中有什么区别 关键字: is 和 = 在 python 中有什么区别 [ 英 ]What is the ...

  9. python分析红楼梦中人物形象_红楼梦中四个人物形象分析

    1 贾宝玉人物分析 通过认真品读石头记, 我认为把贾宝玉作以上评价是不客观. 不合实际的, 是有悖于曹雪芹 本意的. 在我看来, 贾宝玉是一个充满爱心的, 敢于向森严的封建等级制度挑战的革命英雄, 这 ...

  10. python 函数进度条怎么_刷新你对进度条的认识,用python写出不一样的进度条

    1 简介 在日常工作中,我们运行程序经常会用到「循环迭代」,假如这个执行时间很短,那倒也无所谓.但是有一些过程耗时蛮长的,给其加上「进度条」(progress bar),可以帮我们监控代码执行进度,以 ...

最新文章

  1. NSString字体大小计算方法
  2. python Sigmoid和Tanh 可视化
  3. cdoj 1070 秋实大哥打游戏 带权并查集
  4. Firewall配置
  5. CentOS4.4下安装jdk1.5
  6. 2020,国产数据库崭露峥嵘的发轫之年
  7. Android 灯光系统开发
  8. win10诊断启动后联网_2步打开win10隐藏高级启动,解决80%系统问题
  9. Xmapp安装配置和连接MySQL
  10. HDU 2079 选课时间(题目已修改,注意读题)(母函数)
  11. 智能制造:IntelligentSmart Manufacturing有何区别?
  12. chrome18-使用network waterfall分析页面载入性能
  13. 小丁在加班之JVM优化-内存结构
  14. 小程序全套购物车(全选,单选,反选,删除,价格计算)
  15. html3d轮播图片效果,CSS3,3D效果轮播图
  16. 简历中的项目经历怎么写?
  17. 『 云原生·Docker』Docker存储
  18. chatbot使用_如何使用Python构建Chatbot项目
  19. 看这些MySQL的重要知识点,吃透它
  20. hdu 2177 威佐夫博弈

热门文章

  1. python np.arange,np.linspace和np.logspace之间的区别
  2. arc_loss训练手写数字分类
  3. Django项目实战前要做的事情
  4. MySQL高级能量预警
  5. 都9102年了,还问GET和POST的区别
  6. Spring MVC 中使用 Google kaptcha 验证码
  7. HDU 3826 Squarefree number:题目解答源码
  8. poj 2492A Bug's Life(并查集)
  9. Nginx解决PATH_INFO新解决办法
  10. 我与技术------2012程序之路