比起子弹时间和火爆的场景,我更喜欢《黑客帝国》故事背景的假设——人们熟悉的世界是虚构的,是机器输入人脑的幻觉,而且幻象也不是十全十美的,有些地方是不符合自然规律的。这些地方或多或少都显示出幻境世界的破绽和现实世界的模样。如果你看过动画版的《黑客帝国》《超越极限》和《世界纪录》,你会有更深的感受,我们所熟悉并赖以生存的Python世界其实是一个虚拟的世界。这个虚拟世界在向我们展示极其华丽的场景和功能的同时,也有一些超出常识和认知的东西。今天就带大家去探寻其中的一些灵异点,以及背后的现实世界魔法海象算子。海象运算符:=是Python3.8引入的新特性,意思是保存一个临时的变量赋值操作,例如:a=[1,2,3,4,5]n=len(a)ifn>4:print(n)的意思是,如果lista的长度大于4,则打印a的长度,为了避免二次求解,用变量n来存储a的长度,即合理的。如果你使用海象运算符(:=),它将是这样的:a=[1,2,3,4,5]ifn:=len(n)>4:从print(n)可以看出,省略了临时变量n的定义。通过海象算子,我们可以一箭双雕。不得不说Python为了提高我们的效率真是绞尽脑汁。刚刚发布的Python3.9正式版也是为了提高效率,在很多地方进行了改进。但是,看下面的代码>>>a="wtf_walrus">>>a'wtf_walrus'>>>a:="wtf_walrus"#报错!File"",line1a:='wtf_walrus'^SyntaxError:invalidsyntax>>>(a:="wtf_walrus")#奇迹发生了,它过去了!'wtf_walrus'>>>a'wtf_walrus'还有一段>>>a=6,9#元组赋值>>>a#结果正常(6,9)>>>(a:=6,9)#海象赋值,表达式结果正常(6,9)>>>a#临时变量不同6>>>a,b=6,9#解包赋值>>>a,b(6,9)>>>(a,b=16,19)#哦不!File"",line1(a,b=6,9)^SyntaxError:invalidsyntax>>>(a,b:=16,19)#这里实际上打印了一个三元组!(6,16,19)>>>a#问题是a没有变。6>>>b16解密海象非括号表达式的海象赋值操作海象运算符(:=)适用于表达式内部的作用域,不带括号相当于全局作业作用域,对应赋值操作在将受编译器限制的括号中。赋值运算符(=)不能放在括号中,因为它需要在全局范围内执行,而不是在a中表达式中海象运算符的本质海象运算符的语法形式是Name:=expr,Name是anormalidentifier,而expr是一个normalexpression,所以iterablepackingandunpackingperformance的结果会和预期不一样(a:=6,9)实际上会被解析为((a:=6),9),最后,a的值为6,验证一下:>>>(a:=6,9)==((a:=6),9)True>>>x=(a:=696,9)>>>x(696,9)>>>x[0]isa#referencesthesamevalueTruealso,(a,b:=16,19)等价于(a,(b:=16),19,它原来这样一个不安分的字符串首先建立了一个感知>>>a="some_string">>>id(a)140420665652016>>>id("some"+"_"+"string")#以不同的方式创建字符串本质上是相同的。140420665652016奇怪的事情即将发生>>>a="wtf">>>b="wtf">>>aisbTrue>>>a="wtf!">>>b="wtf!">>>aisb#什么鬼!False如果把这段代码写成脚本文件,用Python运行,结果是正确的:a="wtf!"b="wtf!"print(aisb)#会打印True,更神奇的是,在Python3.7之前的版本,会有如下现象:>>>'a'*20is'aaaaaaaaaaaaaaaaaaaaa'True>>>'a'*21is'aaaaaaaaaaaaaaaaaaaaaa'False20个字符加起来等于20个a字符串,并且21不等于揭秘字符串在计算机世界中,任何奇怪的现象都有其原因。这些字符串行为是由于Cpython在编译和优化时有时会处理不可变对象。对于存储,在新引用之间创建引用而不是创建新引用。这种技术称为stringinterning,可以节省内存,提高效率。上面代码中,字符串是隐式常驻的,什么情况下会常驻呢?所有长度为0和1的字符串都将驻留字符串将在编译时驻留,而不是在操作期间驻留("wtf"将驻留,"".join("w","t","f")不会驻留)只有包含字母、数字和下划线的字符串才会常驻,这就是为什么"wtf!"不会常驻(里面有字符!)如果a和b的赋值“wtf!”语句在同一行,Python解释器会创建一个对象,然后让两个变量指向这个对象如果它在不同的行上,解释器将不知道已经有一个“wtf!”object,所以它会创建一个新的(因为“wtf!”不会常驻)在IPython这样的交互式环境中,语句是在一行中执行的,而在脚本文件中,代码是同时编译的,并且有同一个编译环境,所以可以理解在代码文件的不同行中常驻字符串不引用同一个对象的现象。常量折叠(constantfolding)是Python的一种优化技术:窥孔优化(peepholeoptimization),比如a="a"20,这样的语句会在编译时展开,减少运行时消耗,为了不让pyc文件太大了,字符会被展开限制为20,或者想想“a”10**100语句生成的pyc文件有多大注意常量折叠的问题在Python3.7以后的版本中得到了改善,但具体原因不清楚(矩阵变化比较复杂)小心链式操作做show操作>>>(False==False)in[False]#是常识False>>>False==(Falsein[False])#没问题False>>>False==Falsein[False]#你现在感觉如何?True>>>TrueisFalse==FalseFalse>>>FalseisFalseisFalseTrue>>>1>0<1True>>>(1>0)<1False>>>1>(0<1)False我不不知道您看到这段代码时的感受。反正我第一眼看到的时候怀疑自己学的Python是假的~怎么回事?根据Python官方文档,表达式Section,ValueComparisonSubsection说明:一般来说,如果a,b,c,...,y,z是表达式,op1,op2,...,opN是比较运算符,那么aop1bop2c...yopNz等价于aop1bandbop2cand...yopNz,只不过每个表达式只求值一次根据以上知识,重新看上面好像有点迷惑句子:法lseisFalseisFalse等价于(FalseisFalse)and(FalseisFalse)TrueisFalse==False等价于TrueisFalseandFalse==False,现在可以看出第一部分的求值TrueisFalseisFalse,所以整个表达式求值为False1>0<1等价于1>0和0<1,所以表达式求值为True表达式(1>0)<1等价于True<1,而int(True)的值为1,True+1的值为2,则1<1为False。is(yes)oris(yes)直接被下面的代码惊到了>>>a=256>>>b=256>>>aisbTrue>>>a=257>>>b=257>>>aisbFalseonemore>>>a=[]>>>b=[]>>>aisbFalse>>>a=tuple()>>>b=tuple()>>>aisbTrueisalsoanumber,同样是一个对象,所以处理方式不同。。。一一了解is和==的区别is运算符用于检查两个变量是否引用同一个对象实例。==运算符用于检查两个变量引用对象的值是否相等。so用于引用比较,==用于值比较。下面的代码可以更清楚地解释这一点:>>>classA:pass>>>A()isA()#由于两个对象实例在不同的内存空间,表达式值为FalseFalse256是一个存在的对象,但是257不是这个副标题让人很无语,确实物与物不一样。在Python中,-5到256范围内的值是预初始化的。如果value是这个范围内的数字,会直接创建一个reference,否则就是这就解释了为什么同样是257,memory对象的现象不同。你为什么要这样做?官方的解释是这个范围内的值更常用作不可变的空元组和-5到256的值是预先创建的。对于不可变对象,Python解释器也是预先创建的。例如,对于空的元组对象,这是可以解释为什么空列表对象之间的引用不同,但空元组之间的引用确实是相同的。被吞掉的Javascript先看流程some_dict={}some_dict[5.5]="Ruby"some_dict[5.0]="JavaScript"some_dict[5]="Python"print(some_dict[5.5])#Rubyprint(some_dict[5.0])#PythonJavascript在哪里?Python字典对象索引背后的原因是通过键相等查找并比较键的哈希值。具有相同值的不可变对象的哈希值是相同的>>>5==5.0True>>>>hash(5)==hash(5.0)True所以我们可以这样理解,当some_dict[5]="Python"执行时,前面定义的some_dict[5.0]="Javascript"会被覆盖,因为5和5.0有相同的hash值,需要注意的是:有可能不同的值有相同的hash值。这种现象称为散列冲突。关于字典对象使用哈希值作为索引操作的更深层原因,有兴趣的同学可以参考StackOverflow上的回答,解释很精彩,网址是:https://stackoverflow.com/que。..限于篇幅(能量)总结一下,今天给大家介绍一下Python宇宙中的这些异常现象,还有很多异常现象,都包含在satwikkansal的wtfpython(https://github.com/satwikkans)...)任何华丽与美丽的背后,都是各种智慧、技巧、妥协、辛勤的支持。不是有这么一句话吗?:如果你感到自在,就像一个负重行走的人。而这个人就是我们最喜欢的Python和它的编译器。为了更好地理解某件事,您需要了解其背后的概念和原则。我希望这篇简短的文章能对您有所启发。以上就是本次分享的全部内容。想了解更多python知识,请前往公众号:Python编程学习圈,发“J”免费领取,每日干货分享