您好,登錄后才能下訂單哦!
本篇內容主要講解“Ruby與Python的對象系統有什么區別”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Ruby與Python的對象系統有什么區別”吧!
屬性的嚴格定義不知道去哪里找, 這里暫且用來指對象實例用來儲存自身狀態的方式好了。 用途自然是儲存對象的協作者與數據等。 或者干脆說成是: per-instance 的東西都叫屬性1。
一般來說, 對象的內部狀態輕易不向外暴露, 讀寫操作主要由對象的方法完成。 這種自己默默修改自身屬性的存取方式我們暫時稱作內部訪問。
Ruby 中為每個對象提供了單獨的命名空間來存放屬性, 語法上 @foo
是讀取,@foo = 'bar'
是寫入。 而且讀寫語義無法通過元編程來干擾。 也不與常量查找、方法調用、局部變量存取等尋址方式相沖突。
在 Python 中這種命名空間似乎也是存在的, 而且乍一看可以通過 __dict__
字典來訪問2。 但由于打字太多, 實際恐怕很少有人積極使用, 更多地還是直接用外部訪問的方法。 往下看。
Ruby 默認禁止外部直接訪問對象屬性3, 需要我們顯式地在類定義中使用attr
系列方法 來顯式定義供外部使用的存取方法。
Python 這邊就容易得多, 自定義的 New Style Class 默認有 __dict__
屬性4, 讀寫全開, 可以直接用 foo.bar
,foo.bar = 'baz'
語法存取, 內部存取時多半也用這種語法。
這里我不想談及定義了 __slots__
的情況, 因為看文檔里面一長串需要當心的 notes 可以猜測沒什么人愿意用。 稍微 Google 一下的結果也基本證實如此。
兩種語言都支持在語法上依然寫出常規的屬性取值/賦值, 而背后執行任意的代碼。 常用的場景包括延遲求值, 計算屬性(Calculated Attribute), 只讀屬性等。
在 Ruby 里由于語法糖實在太甜, 調用方法時可以省略掉括號, 能夠不傳參數調用的方法就是 getter, 寫起來像 foo.bar
。 以 =
結尾的一元方法就是 setter, 通過 foo.bar = 'baz'
就會調用到。 前面提到的 attr 系列方法 也只是按照這個接口來定義方法, 并非特殊的語言關鍵字。
至于 Python, 只需 getter 時還好說, 直接用 @property
裝飾器就好。 但需要允許外部只讀訪問屬性時就有些麻煩。 讀寫控制要由 property descriptor 來實現, 為了自定義一個只讀 descriptor 寫起來像這樣:
EDIT: 明顯下面的代碼是不對的, 當時我在想什么。 還好真實世界中一般都用下劃線方案而不是用這種方案來滿足語義純化論者。
class Foo(object): bar = property() @bar.setter def bar(self, value): raise AttributeErrorFoo().bar = 'shit' # => 拋 AttributeError 異常
這樣在內部訪問中要寫入屬性時就要被迫改用這種傷鍵盤的寫法:self.__dict__['bar'] = 'blah'
。 所以現實生活中人們往往用下劃線開頭表達私有屬性, 然后定義一個去掉開頭下劃線的 getter 來提供只讀訪問了事。
到這里已經可以總結出我偏好 Ruby 的一點原因:
對屬性的內部與外部存取做出明確區分, 默認不提供外部直接存取。 且兩種存取方式的語法都不難寫。 鼓勵開發者在設計時考慮好封裝問題。 而 Python 慣用的方式是下劃線標識私有屬性, 難免會增加代碼量。
接下來如果再寫下去要一并引入很多對象模型的重點問題, 恐怕就要被標記 TL;DR 了。 所以先到這吧。
未來談及方法解析的時候會引入 per-instance 的方法定義, 從而毀掉這個不嚴格的描述。
但是你沒法通過自定義 __dict__
返回值來擾亂屬性專有字典。 是的, 在這兩種語言元編程的能力下, 可以做出很多出格的事情來。 本文只能在假設開發者不會積極地亂來的基調下展開討論。
當然你可以用 instance_variable_{get,set,s}
等方法來訪問。 避而不談的理由見另一個腳注。
object
類自己卻沒有定義 __dict__
, 其實例也沒有。 所以盡管這樣一個空的 New Style Class class Foo(object): pass
是 object 的直接子類, 兩個類的實例的行為卻大不相同。
到此,相信大家對“Ruby與Python的對象系統有什么區別”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。