Python 對象的身份迷思:從全體公民到萬物皆數

2021-02-19 CSDN

作者 | 豌豆花下貓

責編 | 胡巍巍

這篇文章裡即將說出來的東西,也許你本以為知道了,或者你本以為很熟悉,但是,經過我的分析,我相信你會得到不一樣的感悟,從此以後,你對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=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(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: 
    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技術、數據科學和深度學習,力圖創造一個有趣又有用的學習分享平臺。

聲明:本文為作者投稿,版權歸作者所有。

薦閱讀:


相關焦點

  • 【Python核心編程筆記】一、Python中一切皆對象
    Python中一切皆對象本文首先對比靜態語言以及動態語言,然後介紹 python 中最底層也是面向對象最重要的幾個概念-object、type和
  • 萬物皆數
    低價課程分享我有好課,萬物皆數,清晰完整,學習請加客服微信:43490686 (若
  • 萬物皆數,畢達哥拉斯的宇宙法則
    米利都學派創始人泰勒斯一天到晚念叨著:「萬物起源於水」「水是最好的」。誰知他的弟子阿那克西曼德馬上站出來否定:「水太實際了,萬物起源於具有無限屬性的阿派朗」。話音未落,他的第二個弟子阿那克西美尼又慷慨陳詞:「你們都錯了,萬物起源於氣」。
  • 從「萬物皆數」談起
    「萬物皆數」是畢達哥拉斯的至理名言。他在鐵匠鋪裡發現了 「音樂和聲」與「數」之間的關聯在那些彼此呼應、音調和諧的錘子敲打聲中,有著一種簡單的數學關係。而劍橋大學的地球學家漢斯·亨利克發現,世界上幾乎所有彎曲的河流,從源頭到入海口之間,實際長度與直線距離之比,基本接近於圓周率的值。
  • 快樂學習與萬物皆數與上北京大學
    不說別的,就說兩點吧,快樂學習和考上北大兩件事之數。樂之,好之,知之,不是在快樂中學習,而是在學習中經過思考得到結果,搞明白了一個難題,得到快樂,和西方的心流理論是一樣的。此文說的快樂學習,是在快樂中學習,當然不對,反過來,在痛苦中學習嗎?
  • 西方哲學史:畢達哥拉斯「萬物皆數」
    這個團體從公元前6世紀末到公元3世紀,共延續了800多年。由於「密不外傳」的特點,即是在當時要了解他們內部的情況也是不容易的。幾乎所有的數學、哲學理論都很難指明是畢達哥拉斯本人提出的?還他的某一位學生門徒提出的?畢達哥拉斯學派在數學方面的主要貢獻是:算術、幾何、天文和音樂。
  • 學習Python,怎能不懂點PEP呢?
    PEP的官網是:https://www.python.org/dev/peps/,這也就是PEP 0 的地址。其它PEP的地址是將編號拼接在後面,例如:https://www.python.org/dev/peps/pep-0020/ 就是PEP 20 的連結,以此類推。第一個PEP誕生於2000年,現在正好是18歲成年。到目前為止,它擁有478個「兄弟姐妹」。
  • 萬物皆數 | 數學文化宣講團2020年實踐成果一覽
    2020上半年疫情期間,「萬物皆數」數學文化宣講團的成員們利用假期及課餘時間搜尋趣味數學,構思授課流程,錄製課程視頻,開展線上實踐。團隊成員:張意彤 劉佳佳 劉子涵 王心睿 王  樂2020年下半年開學後,疫情得到了有力的控制,「萬物皆數」數學文化宣講團的志願者們有機會去往上海市第二師範學校附屬小學和同濟大學附屬存志學校進行宣講,傳道授業,引路數學。
  • 歷史的軌跡——從畢達哥拉斯學派「萬物皆數也」說起
    數學從遠古時期發展到今天,從涓涓細流到匯入海洋,我們追溯尋訪它的源頭,是從認識自然數開始的。從1+1=2開始,人類播下了數學的種子,數學的創世紀就開始了。我們的數學之旅從薩摩島的畢達哥拉斯開始。公元前6世紀畢達哥拉斯學派活躍在義大利南部,他們堅信數是宇宙的本原,研究數學就是探索自然的奧秘,數學是寄託了他們的熱情而矢志不渝的信仰——萬物皆數也!第一章 數有形狀如果說認識自然數、研究自然數的性質是數學的起源,那麼東西方數學在起步階段就各自選擇了不同的發展道路。
  • 【小喵科技】Micropython 教程:Python基礎篇1
    還記得之前嘮叨的「萬物皆對象」的五字箴言嗎?那麼對象到底是什麼呢?能看得到摸得著嘛?有了print這個大殺器後我們就可以看清楚對象到底是什麼。type返回的是對象原型,我們可以再試試之前我們已經接觸到的幾個變量類型。
  • 萬物皆可娘,萬物皆可擼,細數各種被紳士們玩壞的娘化物
    萬物皆可娘,萬物皆可擼, 細數各種被紳士們玩壞的娘化物。本文將列舉具被娘化物中比較有代表性的一些作品,如有不全之處,還請多多包涵。NO.1:艦娘;代表作品《艦隊collection》、《碧藍航線》等。無限系統樹說到劍娘,最近比較火的新番《無限系統樹》可以算得上是最好的代表作之一,男主上來就送一把可以化身為「40米長的大砍刀」的妹子。
  • 從0開始學python第8.1節-類和對象
    什麼是面向對象之前我們學習了函數,通過函數將一些特定的邏輯封裝起來。這種將代碼組織起來的方式也叫過程式編程。我們今天學習的面向對象編程則將程序做了更高維度的封裝,用人類更容易理解的方式編程。類&實例中國道德經有一句話:道生一,一生二,二生三,三生萬物,講的是世間的萬物都是從特定的模板裡生出來的。
  • 星際礦亨: 未來 是『』萬物皆數『』的時代
    提起「萬物皆數」,大家先想起的應該是畢達哥拉斯,因為這是由他提出的學派主張,那麼畢達哥拉斯認為:數是萬物的本源。因為他發現數和存在的事物有較多相似之處,比如音律的節奏特性或者事物的比例等,都可以用「數」來表現的,還有自然界當中的很多元素,生活當中的很多事體,包括一種概念,一種是機會,幾乎所有一切的東西無一不可以用數來表述,以數為範型而做出相應的表達。
  • 萬物皆可supreme什麼梗 萬物皆可supreme什麼意思
    萬物皆可supreme什麼梗最近有網友整理了一段土味視頻合集,原本土的掉渣的視頻,加上了supreme的水印之竟然有一絲絲高大上。一個是時尚界的潮流風向標,一個是土味合集,網友將兩者結合,其實就是想表達一種土到極致也可以潮流的含義。
  • 「萬物皆數」的世界,你有管好自己的數據資產麼
    那麼當「萬物皆數」的時代來臨時,這個世界將會是什麼模樣?「在「萬物皆數」的時代,很多事情都可以用數據來加以衡量,因此當整個世界都被數據化之後,其內在的規律就有可能通過數據的管理與分析來認知和洞察,因此大數據也就成為了人類認知和改變世界的一種手段,而數據也在不斷地改變人們的生活方式、經濟規律與商業模式,甚至於驅動整個經濟的創新與變革。」
  • 5分鐘掌握 Python 對象的引用
    python的對象引用也是學習python過程中需要特別關注的一個知識點,特別是對函數參數傳遞,可能會引起不必要的BUG。本文將對引用做一個梳理,內容涉及如下:2. python引用2.1 變量和賦值任何一個python對象都有標籤,類型和值三個屬性。標籤在對象創建後直到內存回收就保持不變,可以理解為內存地址。python在給變量賦值,會把賦值的對象的內存地址賦值給變量。
  • 《思想的力量》閱讀錄4:萬物皆數,解密西方哲學史上神秘的團體
    萬物皆水,萬物皆火,萬物皆氣……公元前六百年左右,希臘最初一些偉大的哲學家,面朝大海,仰望星空、白雲……,陷入了這樣的思考與推論。作為當代人的我們看來,看到這些是能理解他們為什麼會這樣思考的,不足為奇。但當你聽到「萬物皆數」時,應該明白真正的大神出場了。
  • opencv-python獲取圖像:面向對象與面向過程
    這時正好有人走進實驗室,手上帶著一本當時的花花公子雜誌,結果故事發生了……而限於當時實驗室設備和測試圖片的需要,lenna的圖片只摳到了原圖的肩膀部分。Lena圖像在科研領域流行的原因:1.該圖適度的混合了細節、平滑區域、陰影和紋理,從而能很好的測試各種圖像處理算法。
  • 分享通信蔣志祥:數字經濟,萬物數智化
    11月15日,第二屆中國網際網路基礎資源大會期間,在分論壇「數字經濟論壇」,分享通信集團董事局主席蔣志祥發表了主題為《數字經濟:萬物數智化》的演講。第三個十年是從2019年5G發牌開始,開啟了萬物數智化的物聯網大連接時代。OTT的出現對於運營商來說既是機遇又是挑戰,一方面原有傳統的基礎電信業務受到巨大衝擊,面臨管道化危機,OTT帶來的新業務釋放了流量需求翻倍增長;另一方面流量的巨大增長給網際網路經濟帶來了巨大的放大效應,推動了消費升級。
  • 【Python基礎】可迭代對象&迭代器對象及其實現
    首選確保for循環的in後面是一個可迭代對象,這樣就能通過python內置函數iter()得到一個迭代器對象(iterator)這裡拋出了異常,因為數字不是一個可迭代對象那麼問題來了, 為什麼列表和字符串是可迭代對象? 因為這些對象滿足了特殊的接口: