Python数据分析—从全体公民到万物皆数

今日读到一篇文章,甚是有感。

就此分享给大家:“Python对象的身份迷思:从全体公民到万物皆数”

1、全体公民与特权种族

在某种意义上说,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有趣的地方了,一面是全体公民,一面是特权种族,组成了看似矛盾的二元对立结构。

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 = "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。在我看来,定制私人名片要比定制官方名片更优美。能够为自己带盐,想想就觉得鸡冻啦!

3、何为真假,万物皆数

以上说法,不管是全体公民身份与特权种族身份,还是官方名片与私人名片,多少带进了我浅薄的社会经验的偏见。我起初很为一方鸣不平,为一种讨巧的做法鸣得意,但是,现在当我知道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

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

接下来,还是一个铺垫,这次是进阶知识。零值(含整数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有这一层隐秘的身份,我已兴奋不已,再难对这看似不合现代语境、却又流传千古的思想做出任何揣测。

来源:科多大数据

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容