Python中的函數(shù)式編程:不可變的數(shù)據(jù)結(jié)構(gòu)
讓我們首先考慮正方形和長方形。如果我們認為在接口方面,忽略了實現(xiàn)細節(jié),方塊是否是矩形的子類型?
子類型的定義取決于Liskov代換原理。為了成為一個子類型,它必須能夠完成超級類型所做的一切。
如何定義矩形的接口?
zope.interface import Interface class IRectangleInterface: get_length: """Squares can do that""" get_width: """Squares can do that""" set_dimensions length width: """Uh oh"""
如果這是定義,則方塊不能是矩形的子類型;它們不能響應(yīng)set_dimensions方法,如果長度和寬度不同。
另一種方法是選擇制作矩形。不變.
class IRectangleInterface: get_length: """Squares can do that""" get_width: """Squares can do that""" with_dimensions length width: """Returns a new rectangle"""
現(xiàn)在,一個正方形可以是一個矩形。它可以返回一個新的矩形(通常不是正方形)with_dimensions被稱為,但它不會停止成為一個正方形。
這似乎是一個學(xué)術(shù)問題-直到我們考慮到,從某種意義上說,正方形和長方形是它們兩邊的容器。在我們理解了這個例子之后,更實際的情況是使用更傳統(tǒng)的容器。例如,考慮隨機訪問數(shù)組.
我們有ISquare和IRectangle,和ISquare是IRectangle.
我們希望在隨機訪問數(shù)組中放置矩形:
class IArrayOfRectanglesInterface: get_element i: """Returns Rectangle""" set_element i rectangle: """'rectangle' can be any IRectangle"""
我們也想把正方形放在一個隨機存取數(shù)組中:
class IArrayOfSquareInterface: get_element i: """Returns Square""" set_element i square: """'square' can be any ISquare"""
即使ISquare是IRectangle,任何數(shù)組都不能實現(xiàn)這兩者。IArrayOfSquare和IArrayOfRectangle.
為什么不行?假設(shè)bucket實現(xiàn)兩者。
>>> rectangle make_rectangle >>> bucket.set_element rectangle # This is allowed by IArrayOfRectangle >>> thing bucket.get_element # That has to be a square by IArrayOfSquare >>> assert thing.height thing.width Traceback most recent call last: File "<stdin>" line module AssertionError
兩者都不能實現(xiàn),這意味著兩者都不是另一種類型的子類型,盡管ISquare是IRectangle。問題是set_element方法:如果我們有一個只讀數(shù)組,IArrayOfSquare的子類型IArrayOfRectangle.
可變性,都是可變的。IRectangle接口和可變IArrayOf接口使得對類型和子類型的思考變得更加困難-而放棄的能力意味著我們期望類型之間的直觀關(guān)系實際上仍然有效。
突變也可以非局部效果。當(dāng)兩個地方之間的共享對象被一個突變時,就會發(fā)生這種情況。典型的例子是一個線程與另一個線程交互一個共享對象,但是即使在一個單線程程序中,在相距很遠的地方之間共享也很容易。考慮到在Python中,大多數(shù)對象都可以從許多地方訪問:作為一個模塊全局,或者在堆棧跟蹤中,或者作為一個類屬性。
如果我們不能限制共享,我們可能會考慮限制可變。
下面是一個不可變的矩形,它利用AutoS庫:
attr.frozen class Rectangeobject: length attr. width attr. classmethod with_dimensionscls length width: return clslength width
這里是一個正方形:
attr.frozen class Squareobject: side attr. classmethod with_dimensionscls length width: return Rectanglelength width
使用frozen參數(shù),我們可以很容易地創(chuàng)建一個不可變的類。所有艱苦的寫作工作__setitem__正確的做法是別人做的,對我們來說是完全看不見的。
修改對象仍然是容易的,改變它們幾乎是不可能的
too_long Rectangle reasonable attr.evolvetoo_long length
可靠的包裝允許我們有不可變的容器
# Vector of integers a = pyrsistent.v(1, 2, 3) # Not a vector of integers b = a.set(1, "hello")
當(dāng)b不是整數(shù)的向量,任何東西都不會停止。a從成為一個。
萬一a一百萬個元素長了嗎?是b要復(fù)制999 999份嗎?Pyrsistent附帶“大O”性能保證:所有操作都采用O(log n)時間到了。它還附帶了一個可選的C擴展,以提高性能超越大O。
為了修改嵌套對象,它附帶了“轉(zhuǎn)換器”的概念:
blog pyrsistent. title"My blog" linkspyrsistent."github" "twitter" postspyrsistent. pyrsistent.title"no updates" content"I'm busy" pyrsistent.title"still no updates" content"still busy" new_blog blog.transform"posts" "content" "pretty busy"
new_blog將成為不可變的等價物。
'links': 'github' 'twitter' 'posts': 'content': "I'm busy" 'title': 'no updates' 'content': 'pretty busy' 'title': 'still no updates' 'title': 'My blog'
但blog還是一樣的。這意味著任何引用舊對象的人都沒有受到影響:轉(zhuǎn)換只有本土化效果。
當(dāng)分享猖獗時,這是有用的。例如,考慮默認參數(shù):
silly_suma b extrav : extra extra.extenda b return extra
在這篇文章中,我們了解了為什么不變性對于思考我們的代碼是有用的,以及如何在沒有昂貴的性能代價的情況下實現(xiàn)它。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請查看下面相關(guān)鏈接
相關(guān)文章
使用Python實現(xiàn)將PDF轉(zhuǎn)為PDF/A和PDF/X
PDF/A和PDF/X是兩種有特定用途的PDF格式,本文主要介紹了如何使用Python將PDF轉(zhuǎn)換為PDF/A和PDF/X,以及如何將PDF/A格式轉(zhuǎn)換回標(biāo)準(zhǔn)的PDF格式,需要的可以參考下2024-04-04Python??處理?Pandas?DataFrame?中的行和列
這篇文章主要介紹了Python處理Pandas?DataFrame中的行和列,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-09-09Python cx_freeze打包工具處理問題思路及解決辦法
這篇文章主要介紹了Python cx_freeze打包工具處理問題思路及解決辦法的相關(guān)資料,需要的朋友可以參考下2016-02-02采用Psyco實現(xiàn)python執(zhí)行速度提高到與編譯語言一樣的水平
這篇文章主要介紹了采用Psyco實現(xiàn)python執(zhí)行速度提高到與編譯語言一樣的水平的方法,是非常實用的Python第三方庫,需要的朋友可以參考下2014-10-10Python中函數(shù)的基本定義與調(diào)用及內(nèi)置函數(shù)詳解
這篇文章主要給大家介紹了關(guān)于Python中函數(shù)的基本定義與調(diào)用及內(nèi)置函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05Python的Flask項目中獲取請求用戶IP地址 addr問題
這篇文章主要介紹了Python的Flask項目中獲取請求用戶IP地址 addr問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01Flaks基礎(chǔ)之在URL中添加變量的實現(xiàn)詳解
這篇文章主要介紹了在python開發(fā)中,F(xiàn)laks框架之上在URL鏈接中添加變量的實現(xiàn)方式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09