溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Ruby和Python的方法調(diào)用有什么不同

發(fā)布時(shí)間:2021-11-26 11:34:28 來源:億速云 閱讀:132 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容介紹了“Ruby和Python的方法調(diào)用有什么不同”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Property -vs- Method

在 Python 的世界觀里, 對象被當(dāng)作屬性的容器, 調(diào)用方可以在其上 get/set 屬性。 get/set 的邏輯可能是簡單的取值賦值, 也可能是通過 descriptor 實(shí)現(xiàn)的復(fù)雜邏輯。 所謂的 method 只是在查找 property 時(shí)返回了某種特殊的 callable object 而已。

Ruby 則遵從了 Smalltalk 的設(shè)計(jì)原則: 消息傳遞是對象與外界交流的唯一方式, 屬性賦值與取值都是語法糖偽裝下的方法調(diào)用。 僅此。

方法解析

解析一詞譯自 Resolution, 方法解析有時(shí)也稱作方法查找(Lookup)。 解析過程所要解決的問題是 “在接受方法調(diào)用時(shí)找到實(shí)際需要執(zhí)行的代碼”。

由于 Python 對“屬性”及其 descriptor 概念的強(qiáng)調(diào), 方法解析在 Python 里其實(shí)更應(yīng)該稱作屬性解析。

從實(shí)例自身開始解析

Ruby 設(shè)計(jì)了 eigenclass, 使得每個(gè)實(shí)例都可以擁有一個(gè)只屬于自己的 class, 在其中定義屬于自己的方法, 在方法解析的過程中, eigenclass 的優(yōu)先級也最高。 畢竟, 從消息傳遞的角度來看, 對象自主決定如何響應(yīng)消息并不過分。

日常的應(yīng)用開發(fā)中, 使用 eigenclass 最多的時(shí)候就是定義類方法。 還有一個(gè)常用技巧是把動(dòng)態(tài)生成的方法緩存在里面。 Test double 庫更是會(huì)充分利用它定義每個(gè)實(shí)例的行為。

反觀 Python, 對于 Per-instance Polymorphism 的支持僅停留在實(shí)例屬性的基礎(chǔ)上。 或者說,實(shí)例自身只是單純的屬性容器。 如果你真心想玩, 把對象的__class__ 屬性改掉就可以啦。1

沿繼承結(jié)構(gòu)解析

按照類的繼承結(jié)構(gòu)查找方法是最為主要的方法查找路徑, 在學(xué)習(xí)這兩種語言的對象模型時(shí), 都是重點(diǎn)需要理解的知識。

雖然 Ruby 使用 mixin, Python 用的是多繼承。 但兩種機(jī)制在功用上并沒有因此產(chǎn)生很大的差異。

當(dāng)然特殊情況還是存在的: Python 允許開發(fā)者通過自定義 一個(gè) class 的 metaclass 的 .mro() 方法來修改這個(gè) class 的實(shí)例的方法解析路徑。 不清楚這個(gè)明顯改變方法查找順序的接口實(shí)際有多少應(yīng)用。

此外, Python 對象實(shí)例的屬性查找順序與其 class 的屬性查找順序有明顯的交叉。 語義上僅屬于 class 的 staticmethod 與 classmethod 都會(huì)出現(xiàn)在實(shí)例的屬性查找路徑上。 也許這是為了方便使用多半以 utility function 身份存在的 staticmethod, 但也意味著你不能讓 class method 與 instance method/property 重名。 Seriously,在實(shí)例上能取到 class method 不管怎么解釋也實(shí)在是太奇怪了啊。

解析失敗時(shí)的 fallback

Python 有 __getattr__ 這個(gè)機(jī)會(huì)在解析失敗時(shí)由開發(fā)者自行返回一個(gè)屬性。 相應(yīng)地 Ruby 有 method_missing, 但需要返回方法調(diào)用的結(jié)果而不是單純的查找。 這明顯是 message passing 模式下的產(chǎn)物: 你需要對 message 做出響應(yīng), 而不是關(guān)注屬性/方法這些概念。

此外 Python 還可以在查找前就調(diào)用 __getattribute__ / __setattr__, 這也是一個(gè) catch-all 的機(jī)會(huì)。 哦對了,__getattribute__ 能夠截獲所謂”special attributes”(如__dict__)的查找, 而 __getattr__ 則不能。

這方面單純從語言能力上來看,Ruby 似乎要更弱一些的樣子。 但只提供查找失敗的 catch-all 就已經(jīng)足夠?qū)崿F(xiàn)“響應(yīng)任意方法調(diào)用”。 以及,有人記住 Python 那些個(gè) special attributes 了么? 這種語法上沒有區(qū)別但背后邏輯隱隱地不同的設(shè)計(jì), 要么去死記記住, 要么就等著掉坑吧。

方法綁定與調(diào)用

終于說完了方法解析, 接下來的過程就變得簡單了。 所謂綁定只是讓未綁定的方法確定調(diào)用時(shí) self 的指向。 印象中有時(shí)也稱作 context。

在 Python 的方法定義語法看來, 綁定 self 很像是為函數(shù)綁定了首個(gè)參數(shù)。 不知道和所謂的 currify 是不是一回事。 乃至,調(diào)用的時(shí)候如果傳入?yún)?shù)的數(shù)量不對, Python 拋出的異常的信息里還會(huì)把 self 的占位算進(jìn)去, 有效地?cái)_亂你的 debugging。 Ruby 當(dāng)然不存在這種問題。

以及, 由于對“消息傳遞”的強(qiáng)調(diào), Ruby 不像 Python 可以省略調(diào)用時(shí)的括號直接返回一個(gè)已綁定的 method, 而是必須要用另一個(gè)方法 Object#method 來實(shí)現(xiàn)。

換個(gè)角度來看, Python 在這里讓語法-語義變得復(fù)雜, Ruby 則選擇把這種底層邏輯塞進(jìn)一個(gè)貌似無辜的方法里。 于是 Ruby 才能夠做到“方法調(diào)用時(shí)可以省略括號”。 就是因?yàn)?Ruby 不依賴復(fù)雜的語法來表達(dá)語義, 才可以給更多的語法糖讓出空間。

“Ruby和Python的方法調(diào)用有什么不同”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI