真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Python不可變數(shù)據(jù)結(jié)構(gòu)舉例分析

這篇文章主要講解了“Python不可變數(shù)據(jù)結(jié)構(gòu)舉例分析”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Python不可變數(shù)據(jù)結(jié)構(gòu)舉例分析”吧!

蒙城網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),蒙城網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為蒙城上千提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)公司要多少錢,請找那個售后服務(wù)好的蒙城做網(wǎng)站的公司定做!

我們從思考正方形和矩形開始。如果我們拋開實現(xiàn)細(xì)節(jié),單從接口的角度考慮,正方形是矩形的子類嗎?

子類的定義基于里氏替換原則。一個子類必須能夠完成超類所做的一切。

如何為矩形定義接口?

from zope.interface import Interface class IRectangle(Interface):    def get_length(self):        """正方形能做到"""    def get_width(self):        """正方形能做到"""    def set_dimensions(self, length, width):        """啊哦"""

如果我們這么定義,那正方形就不能成為矩形的子類:如果長度和寬度不等,它就無法對 set_dimensions 方法做出響應(yīng)。

另一種方法,是選擇將矩形做成不可變對象。

class IRectangle(Interface):    def get_length(self):        """正方形能做到"""    def get_width(self):        """正方形能做到"""    def with_dimensions(self, length, width):        """返回一個新矩形"""

現(xiàn)在,我們可以將正方形視為矩形了。在調(diào)用 with_dimensions 時,它可以返回一個新的矩形(它不一定是個正方形),但它本身并沒有變,依然是一個正方形。

這似乎像是個學(xué)術(shù)問題 —— 直到我們認(rèn)為正方形和矩形可以在某種意義上看做一個容器的側(cè)面。在理解了這個例子以后,我們會處理更傳統(tǒng)的容器,以解決更現(xiàn)實的案例。比如,考慮一下隨機存取數(shù)組。

我們現(xiàn)在有 ISquareIRectangle,而且 ISequereIRectangle 的子類。

我們希望把矩形放進隨機存取數(shù)組中:

class IArrayOfRectangles(Interface):    def get_element(self, i):        """返回一個矩形"""    def set_element(self, i, rectangle):        """'rectangle' 可以是任意 IRectangle 對象"""

我們同樣希望把正方形放進隨機存取數(shù)組:

class IArrayOfSquare(Interface):    def get_element(self, i):        """返回一個正方形"""    def set_element(self, i, square):        """'square' 可以是任意 ISquare 對象"""

盡管 ISquareIRectangle 的子集,但沒有任何一個數(shù)組可以同時實現(xiàn) IArrayOfSquareIArrayOfRectangle.

為什么不能呢?假設(shè) bucket 實現(xiàn)了這兩個類的功能。

>>> rectangle = make_rectangle(3, 4)>>> bucket.set_element(0, rectangle) # 這是 IArrayOfRectangle 中的合法操作>>> thing = bucket.get_element(0) # IArrayOfSquare 要求 thing 必須是一個正方形>>> assert thing.height == thing.widthTraceback (most recent call last):  File "", line 1, in AssertionError

無法同時實現(xiàn)這兩類功能,意味著這兩個類無法構(gòu)成繼承關(guān)系,即使 ISquareIRectangle 的子類。問題來自 set_element 方法:如果我們實現(xiàn)一個只讀的數(shù)組,那 IArrayOfSquare 就可以是 IArrayOfRectangle 的子類了。

在可變的 IRectangle 和可變的 IArrayOf* 接口中,可變性都會使得對類型和子類的思考變得更加困難 —— 放棄變換的能力,意味著我們的直覺所希望的類型間關(guān)系能夠成立了。

可變性還會帶來作用域方面的影響。當(dāng)一個共享對象被兩個地方的代碼改變時,這種問題就會發(fā)生。一個經(jīng)典的例子是兩個線程同時改變一個共享變量。不過在單線程程序中,即使在兩個相距很遠的地方共享一個變量,也是一件簡單的事情。從  Python 語言的角度來思考,大多數(shù)對象都可以從很多位置來訪問:比如在模塊全局變量,或在一個堆棧跟蹤中,或者以類屬性來訪問。

如果我們無法對共享做出約束,那我們可能要考慮對可變性來進行約束了。

這是一個不可變的矩形,它利用了 attr 庫:

@attr.s(frozen=True)class Rectange(object):    length = attr.ib()    width = attr.ib()    @classmethod    def with_dimensions(cls, length, width):        return cls(length, width)

這是一個正方形:

@attr.s(frozen=True)class Square(object):    side = attr.ib()    @classmethod    def with_dimensions(cls, length, width):        return Rectangle(length, width)

使用 frozen 參數(shù),我們可以輕易地使 attrs 創(chuàng)建的類成為不可變類型。正確實現(xiàn) __setitem__ 方法的工作都交給別人完成了,對我們是不可見的。

修改對象仍然很容易;但是我們不可能改變它的本質(zhì)。

too_long = Rectangle(100, 4)reasonable = attr.evolve(too_long, length=10)

Pyrsistent 能讓我們擁有不可變的容器。

# 由整數(shù)構(gòu)成的向量a = pyrsistent.v(1, 2, 3)# 并非由整數(shù)構(gòu)成的向量b = a.set(1, "hello")

盡管 b 不是一個由整數(shù)構(gòu)成的向量,但沒有什么能夠改變 a 只由整數(shù)構(gòu)成的性質(zhì)。

如果 a 有一百萬個元素呢?b 會將其中的 999999 個元素復(fù)制一遍嗎?Pyrsistent 具有“大 O”性能保證:所有操作的時間復(fù)雜度都是 O(log n). 它還帶有一個可選的 C 語言擴展,以在“大 O”性能之上進行提升。

修改嵌套對象時,會涉及到“變換器”的概念:

blog = pyrsistent.m(    title="My blog",    links=pyrsistent.v("github", "twitter"),    posts=pyrsistent.v(        pyrsistent.m(title="no updates",                     content="I'm busy"),        pyrsistent.m(title="still no updates",                     content="still busy")))new_blog = blog.transform(["posts", 1, "content"],                          "pretty busy")

new_blog 現(xiàn)在將是如下對象的不可變等價物:

{'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ù)的默認(rèn)參數(shù):

def silly_sum(a, b, extra=v(1, 2)):    extra = extra.extend([a, b])    return sum(extra)

感謝各位的閱讀,以上就是“Python不可變數(shù)據(jù)結(jié)構(gòu)舉例分析”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Python不可變數(shù)據(jù)結(jié)構(gòu)舉例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!


網(wǎng)站標(biāo)題:Python不可變數(shù)據(jù)結(jié)構(gòu)舉例分析
網(wǎng)頁路徑:http://weahome.cn/article/jpijih.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部