自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我們可以在同一個(gè)虛擬機(jī)中運(yùn)行Python 2和3代碼而不需要更改代碼嗎?

開(kāi)發(fā) 后端
從理論上來(lái)說(shuō),可以。Zed Shaw 說(shuō)過(guò)一句著名的話,如果不行,那么 Python 3 一定不是圖靈完備的。但在實(shí)踐中,這是不現(xiàn)實(shí)的,我將通過(guò)給你們舉幾個(gè)例子來(lái)說(shuō)明原因。

從理論上來(lái)說(shuō),可以。Zed Shaw 說(shuō)過(guò)一句著名的話,如果不行,那么 Python 3 一定不是圖靈完備的。但在實(shí)踐中,這是不現(xiàn)實(shí)的,我將通過(guò)給你們舉幾個(gè)例子來(lái)說(shuō)明原因。

對(duì)于字典(dict)來(lái)說(shuō),這意味著什么?

讓我們來(lái)想象一臺(tái)擁有 Python 6 的虛擬機(jī),它可以讀取 Python 3.6 編寫的 module3.py。但是在這個(gè)模塊中,它可以導(dǎo)入 Python 2.7 編寫的 module2.py,并成功使用它,沒(méi)有問(wèn)題。這顯然是實(shí)驗(yàn)代碼,但假設(shè) module2.py 包含以下的功能:

  1. def update_config_from_dict(config_dict):
  2. items = config_dict.items()
  3. while items:
  4. k, v = items.pop()
  5. memcache.set(k, v)
  6.  
  7. def config_to_dict():
  8. result = {}
  9. for k, v in memcache.getall():
  10. result[k] = v
  11. return result
  12.  
  13. def update_in_place(config_dict):
  14. for k, v in config_dict.items():
  15. new_value = memcache.get(k)
  16. if new_value is None:
  17. del config_dict[k]
  18. elif new_value != v:
  19. config_dict[k] = v

現(xiàn)在,當(dāng)我們想從 module3 中調(diào)用這些函數(shù)時(shí),我們遇到了一個(gè)問(wèn)題:Python 3.6 中的字典類型與 Python 2.7 中的字典類型不同。在 Python 2 中,字典是無(wú)序的,它們的 .keys(), .values(), .items() 方法返回了正確的序列,這意味著調(diào)用 .items() 會(huì)在字典中創(chuàng)建狀態(tài)的副本。在 Python 3 中,這些方法返回字典當(dāng)前狀態(tài)的動(dòng)態(tài)視圖。

這意味著如果 module3 調(diào)用 module2.update_config_from_dict(some_dictionary),它將無(wú)法運(yùn)行,因?yàn)?Python 3 中 dict.items() 返回的值不是一個(gè)列表,并且沒(méi)有 .pop() 方法。反過(guò)來(lái)也是如此。如果 module3 調(diào)用 module2.config_to_dict(),它可能會(huì)返回一個(gè) Python 2 的字典?,F(xiàn)在調(diào)用 .items() 突然返回一個(gè)列表,所以這段代碼無(wú)法正常工作(這對(duì) Python 3 字典來(lái)說(shuō)工作正常):

  1. def main(cmdline_options):
  2. d = module2.config_to_dict()
  3. items = d.items()
  4. for k, v in items:
  5. print(f'Config from memcache: {k}={v}')
  6. for k, v in cmdline_options:
  7. d[k] = v
  8. for k, v in items:
  9. print(f'Config with cmdline overrides: {k}={v}')

最后,使用 module2.update_in_place() 會(huì)失敗,因?yàn)?Python 3 中 .items() 的值現(xiàn)在不允許在迭代過(guò)程中改變。

對(duì)于字典來(lái)說(shuō),還有很多問(wèn)題。Python 2 的字典在 Python 3 上使用 isinstance(d, dict) 應(yīng)該返回 True 嗎?如果是的話,這將是一個(gè)謊言。如果沒(méi)有,代碼將無(wú)法繼續(xù)。

Python 應(yīng)該神奇地知道類型并會(huì)自動(dòng)轉(zhuǎn)換!

為什么我們的 Python 6 的虛擬機(jī)無(wú)法識(shí)別 Python 3 的代碼,在 Python 2 中調(diào)用 some_dict.keys() 時(shí),我們還有別的意思嗎?好吧,Python 不知道代碼的作者在編寫代碼時(shí),她所認(rèn)為的 some_dict 應(yīng)該是什么。代碼中沒(méi)有任何內(nèi)容表明它是否是一個(gè)字典。在 Python 2 中沒(méi)有類型注釋,因?yàn)樗鼈兪强蛇x的,即使在 Python 3 中,大多數(shù)代碼也不會(huì)使用它們。

在運(yùn)行時(shí),當(dāng)你調(diào)用 some_dict.keys() 的時(shí)候,Python 只是簡(jiǎn)單地在對(duì)象上查找一個(gè)屬性,該屬性恰好隱藏在 some_dict 名下,并試圖在該屬性上運(yùn)行 __call__()。這里有一些關(guān)于方法綁定,描述符,slots 等技術(shù)問(wèn)題,但這是它的核心。我們稱這種行為為“鴨子類型”。

由于鴨子類型,Python 6 的虛擬機(jī)將無(wú)法做出編譯時(shí)決定,以正確轉(zhuǎn)換調(diào)用和屬性查找。

好的,讓我們?cè)谶\(yùn)行時(shí)做出這個(gè)決定

Python 6 的虛擬機(jī)可以標(biāo)記每個(gè)屬性,通過(guò)查找“來(lái)自 py2 的調(diào)用”或“來(lái)自 py3 的調(diào)用”的信息來(lái)實(shí)現(xiàn)這一點(diǎn),并使對(duì)象發(fā)送正確的屬性。這會(huì)讓它變得很慢,并且使用更多的內(nèi)存。這將要求我們?cè)趦?nèi)存中保留兩種版本的代碼,并通過(guò)代理來(lái)使用它們。我們需要加倍付出努力,在用戶背后同步這些對(duì)象的狀態(tài)。畢竟,新字典的內(nèi)存表示與 Python 2 不同。

如果你已經(jīng)被字典問(wèn)題繞暈了,那么再想想 Python 3 中的 Unicode 字符串和 Python 2 中的字節(jié)(byte)字符串的各種問(wèn)題吧。

沒(méi)有辦法了嗎?Python 3 根本就不能運(yùn)行舊代碼嗎?

不會(huì)。每天都會(huì)有項(xiàng)目移植到 Python 3。將 Python 2 代碼移植到兩個(gè)版本的 Python 上推薦方法是在你的代碼上運(yùn)行 Python-Modernize。它會(huì)捕獲那些在 Python 3 上不起作用的代碼,并使用 six 庫(kù)將其替換,以便它在 Python 2 和 Python 3 上運(yùn)行。這是 2to3 的一個(gè)改編版本,用于生成僅針對(duì) Python 3 代碼。Modernize 是首選,因?yàn)樗峁┝烁嗟脑隽窟w移路線。所有的這些在 Python 文檔中的 Porting Python 2 Code to Python 3文檔中都有很好的概述。

但是,等一等,你不是說(shuō) Python 6 的虛擬機(jī)不能自動(dòng)執(zhí)行此操作嗎?對(duì)。Modernize 查看你的代碼,并試圖猜測(cè)哪些是安全的。它會(huì)做出一些不必要的改變,還會(huì)錯(cuò)過(guò)其他必要的改變。但是,它不會(huì)幫助你處理字符串。如果你的代碼沒(méi)有在“來(lái)自外部的二進(jìn)制數(shù)據(jù)”和“流程中的文本數(shù)據(jù)”之間保持界限,那么這種轉(zhuǎn)換就不會(huì)那么輕易。

因此,大項(xiàng)目的遷移不能自動(dòng)完成,并且需要人類進(jìn)行測(cè)試,發(fā)現(xiàn)問(wèn)題并修復(fù)它們。它工作嗎?是的,我曾幫助將一百萬(wàn)行代碼遷移到 Python 3,并且這種切換沒(méi)有造成事故。這一舉措讓我們重新獲得了 1/3 的服務(wù)器內(nèi)存,并使代碼運(yùn)行速度提高了 12%。那是在 Python 3.5 上,但是 Python 3.6 的速度要快得多,根據(jù)你的工作量,你甚至可以達(dá)到 4 倍加速。

親愛(ài)的 Zed

hi,伙計(jì),我關(guān)注你已經(jīng)超過(guò) 10 年了。我一直在觀察,當(dāng)你感到沮喪的時(shí)候,你對(duì) Mongrel 沒(méi)有任何信任,盡管 Rails 生態(tài)系統(tǒng)幾乎全部都在上面運(yùn)行。當(dāng)你重新設(shè)計(jì)它并開(kāi)始 Mongrel 2 項(xiàng)目時(shí),我一直在觀察。我一直在關(guān)注你使用 Fossil 這一令人驚訝的舉動(dòng)。隨著你發(fā)布 “Rails 是一個(gè)貧民窟”的帖子,我看到你突然離開(kāi)了 Ruby 社區(qū)。當(dāng)你開(kāi)始編寫《笨方法學(xué) Python》并且開(kāi)始推薦它時(shí),我感到非常興奮。2013 年我在 DjangoCon Europe 見(jiàn)過(guò)你,我們談了很多關(guān)于繪畫,唱歌和倦怠的內(nèi)容。你的這張照片是我在 Instagram 上的第一個(gè)帖子。

你幾乎把另一個(gè)“貧民區(qū)”的行動(dòng)與 “反對(duì) Python 3” 案例 文章拉到一起。我認(rèn)為你本意是好的,但是這篇文章引起了很多混淆,包括許多人覺(jué)得你認(rèn)為 Python 3 不是圖靈完整的。我花了好幾個(gè)小時(shí)讓人們相信,你是在開(kāi)玩笑。但是,鑒于你對(duì)《笨方法學(xué) Python》的重大貢獻(xiàn),我認(rèn)為這是值得的。特別是你為 Python 3 更新了你的書。感謝你做這件事。如果我們社區(qū)中真的有人因你的帖子為由要求將你和你的書列入黑名單,而請(qǐng)他們出去。這是一個(gè)雙輸?shù)木置?,這是錯(cuò)誤的。

說(shuō)實(shí)話,沒(méi)有一個(gè)核心 Python 開(kāi)發(fā)人員認(rèn)為 Python 2 到 Python 3 的轉(zhuǎn)換過(guò)程會(huì)順利而且計(jì)劃得當(dāng),包括 Guido van Rossum。真的,可以看那個(gè)視頻,這有點(diǎn)事后諸葛亮的意思了。從這個(gè)意義上說(shuō),我們實(shí)際上是積極地相互認(rèn)同的。如果我們?cè)僮鲆淮危鼤?huì)看起來(lái)不一樣。但在這一點(diǎn)上,在 2020 年 1 月 1 日,Python 2 將會(huì)到達(dá)終結(jié)。大多數(shù)第三方庫(kù)已經(jīng)支持 Python 3,甚至開(kāi)始發(fā)布只支持 Python 3 的版本(參見(jiàn) Django科學(xué)項(xiàng)目關(guān)于 Python 3 的聲明)。

我們也積極地就另一件事達(dá)成一致。就像你于 Mongrel 一樣,Python 核心開(kāi)發(fā)人員是志愿者,他們的工作沒(méi)有得到報(bào)酬。我們大多數(shù)人在這個(gè)項(xiàng)目上投入了大量的時(shí)間和精力,因此我們自然而然敏感于那些對(duì)他們的貢獻(xiàn)不屑一顧和激烈的評(píng)論。特別是如果這個(gè)信息既攻擊目前的事態(tài),又要求更多的自由貢獻(xiàn)。

我希望到 2018 年會(huì)讓你忘記 2016 發(fā)布的帖子,有一堆好的反駁。我特別喜歡 eevee(LCTT 譯注:eevee 是一個(gè)為 Blender 設(shè)計(jì)的渲染器)。它特別針對(duì)“一起運(yùn)行 Python 2 和 Python 3 ”的場(chǎng)景,這是不現(xiàn)實(shí)的,就像在同一個(gè)虛擬機(jī)中運(yùn)行 Ruby 1.8 和 Ruby 2.x 一樣,或者像 Lua 5.3 和 Lua 5.1 同時(shí)運(yùn)行一樣。你甚至不能用 libc.so.6 運(yùn)行針對(duì) libc.so.5 編譯的 C 二進(jìn)制文件。然而,我發(fā)現(xiàn)最令人驚訝的是,你聲稱 Python 核心開(kāi)發(fā)者是“有目的地”創(chuàng)造諸如 2to3 之類的破壞工具,這些由 Guido 創(chuàng)建,其最大利益就是讓每個(gè)人盡可能順利,快速地遷移。我很高興你在之后的帖子中放棄了這個(gè)說(shuō)法,但是你必須意識(shí)到你會(huì)激怒那些閱讀了原始版本的人。對(duì)蓄意傷害的指控最好有強(qiáng)有力的證據(jù)支持。

但看起來(lái)你仍然會(huì)這樣做。就在今天你說(shuō) Python 核心開(kāi)發(fā)者“忽略”嘗試解決 API 的問(wèn)題,特別是 six。正如我上面寫的那樣,Python 文檔中的官方移植指南涵蓋了 six。更重要的是,six 是由 Python 2.7 的發(fā)布管理者 Benjamin Peterson 編寫。很多人學(xué)會(huì)了編程,這要?dú)w功于你,而且由于你在網(wǎng)上有大量的粉絲,人們會(huì)閱讀這樣的推文,他們會(huì)相信它的價(jià)值,這是有害的。 

我有一個(gè)建議,讓我們把 “Python 3 管理不善”的爭(zhēng)議擱置起來(lái)。Python 2 正在死亡,這個(gè)過(guò)程會(huì)很慢,并且它是丑陋而血腥的,但它是一條單行道。爭(zhēng)論那些沒(méi)有用。相反,讓我們專注于我們現(xiàn)在可以做什么來(lái)使 Python 3.8 比其他任何 Python 版本更好。也許你更喜歡看外面的角色,但作為這個(gè)社區(qū)的成員,你會(huì)更有影響力。請(qǐng)說(shuō)“我們”而不是“他們”。 

責(zé)任編輯:龐桂玉 來(lái)源: Linux中國(guó)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)