作者 | 豌豆花下猫

责编 | 胡巍巍

这篇文章里即将说出来的东西,也许你本以为知道了,或者你本以为很熟悉,但是,经过我的分析,我相信你会得到不一样的感悟,从此以后,你对Python的理解也会更深一步。

全体公民与特权种族

在某种意义上说,Python世界是普遍公平的,因为所有的子民都是对象“公民”,这在任何一个现实社会里,乃至于在虚拟的国度里,都是极其罕见的。对象们分属在五大部落里(数字、字符串、列表、元祖、字典),各有所长,各司其职,协作共处,通婚繁衍。

还有一点难得的是,他们没有受到愚民政策的对待,全民都享有思想自由,还习得了超便利的自省能力。人能自知,这能力弥足珍贵。

虽然在这个世界里,不会时常出现岗哨拦阻,但在任何有需要的时候,他们都可以自证清白,id()和type()是一种通行语言,你不需要翻译来对接。而对于更进一步的询问,长得相似的两个对象只需一个简明的判断句,就能区分清楚。请你看一段对话:

Object1=2018
Object2="2018"
id(Object1) >>>2399282764784
id(Object2) >>>2399281922600
type(Object1) >>>int
type(Object2) >>>str
Object1 is Object2 >>>False

全体皆公民,这项天赋权力让我对Python产生了良好的印象。不过,随着对它的认识加深,我发现它还暗地里制定了很多“效率优先”的规则。

最明显的例子就是——“特权种族”。从现有的证据来看,特权种族至少包括了:一些数值较小的数字对象(区间:[-5,256])、布尔值对象、None对象、较短的字符串对象(长度不超过20,且仅包括下划线、数字、字母的字符串)等等,还不知道这份名单漏了谁。

效率优先的规则允许这些对象传承内存地址,也就是说,当一个“祖先”对象抢占了一块内存地盘后,所有它那一脉的“子孙后代”都会继承它的遗产(视为同一个对象)。

a=100
b=1000
# c与a共用id,d另立门户
c=100
d=1000
id(a)==id(c) >>>True
id(b)==id(d) >>>False

设想一下,两个祖先(a和b)占了相邻的两块内存,一个可以与它的“后代”共用内存,一个却只能让“后代”另立门户;当它们走完自己的生命周期后,b会马上被当垃圾回收,内存地址遗产被剥夺,然而a却形灭而实存,荫庇后世。

Python为这些对象倾斜资源,也就是为某种阶层固化提供了合法性。划分的依据是因为它们比较常用,共用内存就意味着减少开支,提高内存使用效率。

这就是Python有趣的地方了,一面是全体公民,一面是特权种族,组成了看似矛盾的二元对立结构。

官方名片与私人名片

除了上面的群体性身份外,我发现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 = "Hello pythonCat!
"
repr(words) >>>'Hello pythonCat!
'
str(words)  >>>'Hello pythonCat!
'
# 结合print,注意换行符

print(repr(words))
>>>'Hello pythonCat!
'
print(str(words)) 
>>>Hello pythonCat! # 再加换行
>>>

一个对象的字符串形式就是它的“脸面”,是向他人介绍自己的一张名片。前面提到过,Python世界有五大部落,这些部落的原住民们与生俱来就拥有这两张名片。

对于原住民来说,这两张名片似乎没啥区别,除了在使用打印函数的时候,在换行符等用法上会有不同。

而对于外来人口(例如,自定义的类),如果它没有定做名片(即实现__repr__() 和__str__() 方法)的话,其默认的名片就会是类名及内存地址,如下所示。

class Person:
     def __init__(self,name,sex):
         self.name = name
         self.sex = sex

me = Person("pythonCat", "male")

repr(me)
>>> '<__main__.Person object at 0x0000022EA8D7ED68>'
str(me)
>>> '<__main__.Person object at 0x0000022EA8D7ED68>'

事实上,repr()返回的是对象的官方名片,通常人们会说,这张名片是给机器阅读的。本质上,它就是一个对象的代码表示形式,可以用来重新构造这个对象。通过eval()函数,你可以利用这张名片,重新构造出这个对象。

eval()函数是个内置函数,它将字符串str当成有效的表达式来求值并返回计算结果。也就是eval(repr(x))==x,示例如下:

a = 1 + 1
b = [1, 2, 'cat']
c = {'name':'pythonCat', 'sex':'male'}
eval(repr(a)) >>>2
eval(repr(b)) >>>[1, 2, 'cat']
eval(repr(c)) >>>{'name': 'pythonCat', 'sex': 'male'}

相对地,str()得到的是对象的私人名片,通常有更友好的表现形式,因为它是为人类阅读而设计的。

如果一个对象公民没有私人名片,那Python默认会调用它的官方名片。因为这个机制,很多人建议如果要定制一个名片,最好是定制官方那个。但是我却不认同,我认为应该定制私人的那个,因为这样发挥空间更大。不张扬个性,毋宁死。

class Person:
     def __init__(self,name,sex):
         self.name = name
         self.sex = sex
     # 定制私人名片
     def __str__(self):
         return "{} is an elegant creature!".format(self.name)

me = Person("pythonCat", "male")

repr(me)
>>>'<__main__.Person object at 0x000002E6845AC390>'
str(me)
>>>'pythonCat is an elegant creature!'

在《The Zen of Python》里第一句话就是:Beautiful is better than ugly。在我看来,定制私人名片要比定制官方名片更优美。能够为自己带盐,想想就觉得鸡冻啦!

何为真假,万物皆数

以上说法,不管是全体公民身份与特权种族身份,还是官方名片与私人名片,多少带进了我浅薄的社会经验的偏见。我起初很为一方鸣不平,为一种讨巧的做法鸣得意,但是,现在当我知道Python中另一种更不为人知的身份现象的时候,我就释然了。

我接下来要揭示的身份话题,已经超越了社会学和心理学范畴,进入了一种哲学的思想疆域。

前方高能!

前方高能!

前方高能!

首先,来做一个基础知识的铺垫。Python有一个令大部分编程语言都忘尘莫及的特性,那就是,所有对象都可以用于做真假判断。

在做判断的时候,以下情况都视为假(False):None、数值的零值、空序列(如空字符串""、空列表[]、空元祖() )、空集合{} 等等。除此之外,一般对象都可以作为真值(True)来使用。来看示例:

list = [1, 2]
if list: # 即if True
    print("list is not empty")
else:
    print("list is empty")

>>> list is not empty

判断一个列表是否为空,你不需要写iflen(list)>0,或者写iflist==[],简明的使用方法是iflist或者ifnotlist,有物则为真,无物则为假。其它判断情况类似。

接下来,还是一个铺垫,这次是进阶知识。零值(含整数0、浮点0.0、虚数0j等)可以映射为False,其它非零值映射为True;但是,反过来,False唯一映射整数0,True唯一映射整数1。

这意味着,可以拿False、True做数学运算。

True + 1 >>>2
True + 1.0 >>>2.0
False + False >>>0
True + (True*2) >>>3
True/2*5 >>>2.5

两个铺垫之后,接下来进入正题了。真正的前方高能!

第一个铺垫告诉我们,对象可以映射成布尔值(True真False假),第二个铺垫告诉我们,布尔值可以映射成数字(1和0)。

你是否觉察出什么了呢?你是否开始好奇,True和Flase到底是什么东西了呢?这到底是什么原理啊?还有,为什么会存在这样的设定呢?

见证真相的时刻到了——在Python中,布尔值其实是整数对象的子类

type(True) >>> bool
isinstance(True,int)  >>>True
isinstance(False,int) >>>True

啊!哪有什么真真假假,真假并不是本质的存在,真假其实只是数啊!

再回看前面两个铺垫,结合起来,那不就是说,所有对象都映射成了数么?

我不由得想起了2500年前,古希腊哲学家与数学家毕达哥拉斯的哲学命题——万物皆数 !

难道这竟是Python的哲学么?总不会是一种巧合吧?

我突然觉得智商不足,思辨受阻。得知布尔值True和False有这一层隐秘的身份,我已兴奋不已,再难对这看似不合现代语境、却又流传千古的思想做出任何揣测。

作者简介:豌豆花下猫,某985高校毕业生, 兼具极客思维与人文情怀 。公众号Python猫, 专注python技术、数据科学和深度学习,力图创造一个有趣又有用的学习分享平台。

声明:本文为作者投稿,版权归作者所有。

荐阅读:

  • Google 不要 Android 了?新系统 Fuchsia 或将支持 Java

  • 王思聪“杀死”微博

  • 寒冬已至?四面楚歌的 Android 工程师该何去何从?

  • AR热度不在? NO! 三星开发者大会将聚焦AR

  • 热职推荐|精通Java/Python就能月薪40k? 北上广深渝蓉10大热门公司等你来!

  • 我混IT这么久,什么「山寨货」没见过?

  • 2018 AI产业投融资分析:热钱涌向何处,谁的“寒冬”将至?

  • 社畜码农

Python 对象的身份迷思:从全体公民到万物皆数相关推荐

  1. 阿里巴巴400集python教程_阿里巴巴推荐的400集Python视频合集免费学起来,学完万物皆可爬...

    Python是一种跨平台的计算机程序设计语言.随着版本的不断更新和语言新功能的增加越多的被用于大型的,独立的开发,是高级语言中的胶水语言,被无数人追捧! 随着社会发展的越来越快,Python的优点马上 ...

  2. 大佬打造的400集Python视频合集免费学起来,学完万物皆可爬

    Python已经成为一种再主流不过的编程语言了.它天生丽质,易于读写,非常实用,从而赢得广泛的群众基础,被誉为"宇宙最好的编程语言",被无数程序员热烈追捧. 随着时代的发展越来越快 ...

  3. 迷思:Python学到什么程度可以面试工作?

    迷思:Python学到什么程度可以面试工作? Python学习者越来越多,现在中国对Python的使用量已经跃居全球首位,越来越多的高手都使用 Python来编写框架.制作工具.完成功能,那么开发功能 ...

  4. Python对象的空间边界:独善其身与开放包容

    ♚ 豌豆花下猫,某985高校毕业生, 兼具极客思维与人文情怀 .公众号Python猫, 专注python技术.数据科学和深度学习,力图创造一个有趣又有用的学习分享平台. 睡觉是我最爱做的事--因为可以 ...

  5. javascript”面向对象编程”- 1万物皆对象

    javascript几乎成了如今web开发人员必学必会的一门语言,但很多人却只停在了一些表单验证等基础操作层面上,在面向对象语言大行其道的当下,我们需要去学习javascript的面向对象的知识,以便 ...

  6. python内建函数测试对象身份_Python学习笔记 03 Python对象

    1.Python对象 Python对象都拥有三个特性:身份.类型和值. 身份:每一个对象都有一个唯一的身份标识自己,任何对象的身份都可以使用内建函数id()来得到.这个值可以被认为是该对象的内存地址. ...

  7. python内建函数测试对象身份_python 学习笔记day03-python基础、python对象、数字、函数...

    python基础 语句和语法 注释及续行 首要说明的是:尽管python可读性最好的语言之一,这并不意味者程序员在代码中就可以不写注释 和很多UNIX脚本类似,python注释语句从#字符开始 注释可 ...

  8. ​赠书:面向对象的两大迷思,再给你们解答一次

    面向对象是目前最流行的一种程序设计和实现思想.无论从事企业级开发.互联网应用开发,还是手机软件开发,都会用到面向对象的技术. 在主流的编程语言中,C++.Java.C#.PHP.Python等都是支持 ...

  9. Python学习笔记《Python核心编程》第4章Python对象

    所有的python对象都拥有三个特性:身份,类型和值 身份:每个对象都有一个唯一的身份标识自己,可以使用内建函数id()来得到,这个值被认为是该对象的内存地址:--只读 类型:对象的类型决定了该对象可 ...

最新文章

  1. badboy 不支持html5,html5_iframe.htm
  2. QT 生成二维码接口封装
  3. 学习笔记-----关于VS中使用模板类出现无法解析的外部符号问题
  4. jvm 性能调优工具之 jstat
  5. Python实例讲解 -- tkinter canvas (设置背景图片及文字)
  6. JavaScript 原始数据类型转换
  7. 自学python能找到工作吗-自学Python如何找工作?多久能找到工作?
  8. 黑马程序员全套Java教程_Java基础入门视频教程零基础自学Java必备教程视频讲义(4)
  9. 十大门店进销存管理系统软件测评,商陆花长年稳居排名榜首
  10. 给应用程序注入钩子程序
  11. 史上最全微信运营工具
  12. 自适应t分布与动态边界策略改进的算术优化算法
  13. 在计算机中 总线简称,微机中的总线一般分为几等
  14. 九九乘法表打印Python
  15. C#和C++字符串拼接的性能分析
  16. php 微信公众号超链接,微信公众帐号开发教程第8篇-文本消息中使用网页超链接_PHP教程...
  17. Java基础面试题(史上最全基础面试题,精心整理100家互联网企业面经)
  18. 论文笔记:CLIP:Learning Transferable Visual Models From Natural Language Supervision详解
  19. 移植u-boot-1.3.4到GT2440(第二版2.0)
  20. nth_element()

热门文章

  1. windows下cuda10.0+cudnn的配置
  2. 在gcp终端中使用ssh连接到本地机器
  3. 数字测图原理与方法的实习日志_数字测图原理与方法实习与习题.doc
  4. echarts-X轴不从0刻度开始 代码实现
  5. 联想笔记本那些有手写功能_联想高端翻转本YOGA C940开启促销 配一体式转轴音响还可私人订制...
  6. ubuntu 下 使用vmware 虚拟xp 声卡没声音 解决
  7. 拉拢苹果用户,谷歌推出“从 iOS 转移到 Android” App
  8. 今天,你的安卓 App 崩了吗?
  9. 理解了这三点,才敢说自己会写Python代码
  10. 第八届开源操作系统年度技术会议(OS2ATC)在京召开, 百位科技菁英到场共鉴“开源协作”