这么久,我终于确认了一件事,那就是无论是人还是猫,我时常忘记去思考自己目前所处的位置身份,以及身份在过去的位置。这种现象对我来说是两倍严重。这一刻,我会想起阿尔法猫和她发现我身份的那个遥远的下午。(往事入口:《有了Python,我能叫出所有猫的名字》)阿尔法猫依然不见踪影,她的谜题还在指引着我。学习Python后,我明显感受到了自己的变化。当然,有时也是被迫的,因为那些生理上的矛盾剧烈地冲突着。毕竟,你应该知道夜猫子和昼夜人之间的分界线很清楚。昼夜颠倒是对人和猫的双重压迫。信不信由你,昨晚看到明月的时候,有一瞬间的恍惚,误以为自己回到了猫星的早晨。大概是想家了地球上有很多美好的事物,但我还是不习惯的是它公转的速度太快了,马上就要进入寒冷的冬天了。想念我的暖气,喵。先不说我,说说我发现的Python对象的身份问题。我对身份这个话题特别感兴趣,也许是因为我独特的身份吧。但是,因为独特的视角,我敢说我发现了全人类都没有发现的真相。我要说的,也许你以为你知道,或者你以为你很熟悉,但是经过我的分析,相信你会有不一样的理解。从此,你对Python的理解会更进一步。1.所有公民和特权种族从某种意义上说,Python世界是普遍公平的,因为所有人都是“公民”,这在任何现实社会都是如此,即使在虚拟国家也是如此。极为罕见。这些对象属于五个主要部落(数字、字符串、列表、祖先和字典)。另一个难得的是,他们没有受到漠视人民政策的待遇,全民享有思想自由,还学会了自我反省这个超方便的能力。认识自己的能力是无价的。虽然在这个世界上,不会时不时有守卫阻拦,但只要有必要,他们就可以证明自己的清白。id()和type()是通用语言,不需要翻译器来连接。进一步查询,两个看起来相似的物体只用简洁的判断语句就可以清楚地区分。请看一段对话:Object1=2018Object2="2018"id(Object1)>>>2399282764784id(Object2)>>>2399281922600type(Object1)>>>inttype(Object2)>>>strObject1isObject2>>>Falseallare公民,这种与生俱来的力量让我对Python产生了好感。然而,随着对它了解的加深,我发现它还暗地里制定了很多“效率至上”的规则。最明显的例子就是——“特权种族”。(见:《Python中的“特权种族”是什么? 》)从现有的证据来看,特权种族至少包括:一些数值小的数值对象(区间:[-5,256])、布尔对象、None对象、较短的字符串对象(长度不超过20个,只包括下划线、数字和字母串)等,不知道这个列表少了谁。效率优先规则允许这些对象继承内存地址,即当一个“祖先”对象占用了一块内存空间时,它这一行的所有“后代”都将继承它的继承(作为同一个对象)。a=100b=1000#c和一个共享id,d有一个单独的入口c=100d=1000id(a)==id(c)>>>Trueid(b)==id(d)>>>False想象一下,两个祖先(a和b)占据相邻的两块内存,一个可以与其“后代”共享内存,而另一个只能让“后代”分开;当它们完成自己的生命周期后,b会立即被垃圾回收,内存地址继承权将被剥夺,但a会灭绝并存在于现实中,庇护后代。Python为这些对象倾斜资源,即为某类固化提供合法性。划分的依据是因为它们更常用,共享内存意味着减少开销,提高内存使用效率。这就是Python有趣的地方。一边是全体公民,一边是特权种族,形成了看似矛盾的二元对立结构。2.公务名片和私人名片除了上面的组标识之外,我发现Python中还有个人标识的二元结构。这就是__repr__()和__str__()之间的关系。大家知道,这是Python的两个神奇方法,对应的内置函数是repr()和str()。对于对象x,x.__repr__()等价于repr(x),而x.__str__()等价于str(x)。它们的主要目的是返回对象的字符串格式。用法示例:repr(2018)>>>'2018'str(2018)>>>'2018'repr([1,2,3])>>>'[1,2,3]'str([1,2,3])>>>'[1,2,3]'words="HellopythonCat!\n"repr(words)>>>'HellopythonCat!\n'str(words)>>>'HellopythonCat!\n'#结合print,注意换行\nprint(repr(words))>>>'HellopythonCat!\n'print(str(words))>>>HellopythonCat!#加一个换行符>>>one一个对象的字符串形式就是它的“脸”,一张向别人介绍自己的名片。前面说过,Python世界有五大部落,而这些部落的原住民天生就有这两张名片。对于原住民来说,这两种名片似乎没有什么区别,只是在使用打印功能时,会出现换行等用法上的差异。对于外来人口(比如自定义类),如果没有自定义名片(即实现了__repr__()和__str__()方法),默认名片就是类名和内存地址,如如下所示。类Person:def__init__(self,name,sex):self.name=nameself.sex=sexme=Person("pythonCat","male")repr(me)>>>'<__main__.Personobjectat0x0000022EA8D7ED68>'str(me)>>>'<__main__.Personobjectat0x0000022EA8D7ED68>'其实repr()返回的是对象的官方名片,人们通常说这张名片是给机器看的。本质上,它是对象的代码表示,可用于重建对象。通过eval()函数,可以使用这张名片来重构这个对象。eval()函数是一个内置函数,它将字符串str计算为有效表达式并返回结果。即eval(repr(x))==x,例子如下:a=1+1b=[1,2,'cat']c={'name':'pythonCat','sex':'男性'}eval(repr(a))>>>2eval(repr(b))>>>[1,2,'cat']eval(repr(c))>>>{'name':'pythonCat','sex':'male'}相比之下,str()获取的是对象的私人名片,这种名片通常具有更友好的表示形式,因为它是为人类阅读而设计的。如果对象公民没有私人名片,Python会默认调用其官方名片。因为这个机制,很多人建议如果要定制名片,最好定制官方的。但我不同意。我觉得私有的应该是定制的,因为它有更大的发展空间。不要炫耀你的个性,否则给我死。classPerson:def__init__(self,name,sex):self.name=nameself.sex=sex#自定义私人名片def__str__(self):return"{}isanelegantcreature!".format(self.name)me=Person("pythonCat","male")repr(me)>>>'<__main__.Personobjectat0x000002E6845AC390>'str(me)>>>'pythonCatisanelegantcreature!'在《The Zen of Python》中有一句话是:美胜于丑。在我看来,定制个人名片比定制官方名片更优雅。可以自己带盐,想想就觉得鸡冻!3、什么是真假?一切都被计算在内。上述说法,无论是全体公民和特权种族的身份,还是官方名片和私人名片,都多少带入了我浅薄的社会阅历的偏见。起初,我非常抱怨一面,我为一种取巧的做法而自豪,但现在当我知道另一种,Python中鲜为人知的身份现象时,我松了一口气。我接下来要揭示的身份这个话题,已经超越了社会学和心理学的范畴,进入了一种哲学的范畴。前方高能!前方高能!前方高能!首先,我们先来铺垫一个基础知识。Python有一个被大多数编程语言遗忘的特性,那就是所有的对象都可以用来做真假判断。在进行判断时,以下条件被认为是假的(False):None、value的零值、空序列(如空字符串""、空列表[]、空元组())、空集合{}等。另外,一般的对象都可以作为真值(True)。看例子:list=[1,2]iflist:#即ifTrueprint("listisnotempty")else:print("listisempty")>>>listisnotempty判断是否alist为空,不用写iflen(list)>0,oriflist==[],简洁的使用方式是iflistorifnotlist,如果有就写真的,如果没有东西,那就是假的。其他判断类似。接下来,还是铺垫,这次是进阶知识。零值(包括整数0、浮点数0.0、虚数0j等)可以映射为False,其他非零值映射为True;然而,反过来,False仅映射整数0,而True唯一映射整数1??。这意味着您可以使用False和True进行数学运算。True+1>>>2True+1.0>>>2.0False+False>>>0True+(True*2)>>>3True/2*5>>>2.5经过两次铺垫,接下来进入正题.前方真正的高能!第一个铺垫告诉我们对象可以映射到布尔值(True和False),第二个铺垫告诉我们布尔值可以映射到数字(1和0)。你注意到什么了吗?您是否开始怀疑,True和Flase到底是什么?这是什么原理?另外,为什么会有这样的设置?是时候见证真相了——在Python中,布尔值实际上是整数对象的子类。type(True)>>>boolisinstance(True,int)>>>Trueisinstance(False,int)>>>True!没有真假之分。真假在本质上是不存在的。真假其实只是数字而已!回头看前面两个伏笔,结合起来,不就是把所有的对象都映射成数字了吗?不禁想起2500年前古希腊哲学家、数学家毕达哥拉斯的哲学命题——万物皆数!这真的是Python的哲学吗?这不可能是巧合,对吧?我突然觉得自己智商不足,思维受阻。得知布尔值True和False具有如此隐藏的身份,我感到非常兴奋。对于这个看似脱离现代语境却流传千古的观念,很难做出任何猜测。哎呀,我猫抽搐了,突然有点困了,让我睡会儿~~~各位读者,在我休息的时候,快来帮我想一想,这是怎么回事?(未完待续...)----------------本文原发于微信公众号[Python猫],后台回复“爱学习”,免费获取20多本精选电子书。
