Pythonの関数プログラム:可変ではないデータ構造


まず正方形と長方形を考えましょう。インターフェースの場合、実装の詳細を無視して、ブロックは矩形のサブタイプですか?
サブタイプの定義は、Liskyov置換原理に依存する。サブタイプになるためには、スーパータイプのすべてを完成させなければなりません。
長方形のインターフェースはどう定義しますか?

zope.interface import Interface
class IRectangleInterface:
get_length:
"""Squares can do that"""
get_width:
"""Squares can do that"""
set_dimensions length width:
"""Uh oh"""
これが定義されている場合、正方形は矩形のサブタイプではありません。それらはセットに応答できません。dimensions法は,長さと幅が異なるならば。
もう一つの方法は長方形を作ることです。不変です

class IRectangleInterface:
get_length:
"""Squares can do that"""
get_width:
"""Squares can do that"""
with_dimensions length width:
"""Returns a new rectangle"""
現在、正方形は長方形でもいいです。新しい長方形(通常は正方形ではない)を返します。with_dimensionsは正方形になることを止めません。
これは学術問題のようです。つまり、正方形と長方形は両方の容器です。この例を理解した後,より現実的な場合はより伝統的な容器を使用することである。例えば、ランダムアクセス配列を考慮します。
私たちはISquareとIretangleがあります。そしてISquareはIretangleです。
ランダムアクセス配列に矩形を配置したいです。

class IArrayOfRectanglesInterface:
get_element i:
"""Returns Rectangle"""
set_element i rectangle:
"""'rectangle' can be any IRectangle"""
私たちも正方形をランダムアクセス配列に置きたいです。

class IArrayOfSquareInterface:
get_element i:
"""Returns Square"""
set_element i square:
"""'square' can be any ISquare"""
ISquareがIretangleであっても、どの配列もこの両者を実現できない。IArrayOfSquareとIArrayOfRectangle.
どうしてだめですか両方が実装されると仮定する。

>>> 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
どちらも実現できないということは、どちらも他のタイプのサブタイプではないことを意味しています。問題はセットですelement方法:読み取り専用の配列があれば、IArrayOfSquareのサブタイプIArrayOfRectangle.
可変性は、すべて可変です。Ireectangleインターフェースと可変IArrayOfインターフェースは、タイプとサブタイプに対する思考をより困難にすることを可能にする。諦めの能力は、私たちが望むタイプの間の直観関係が実際にはまだ有効であることを意味する。
突然変異は非局所的効果もある。二つの場所の間の共有オブジェクトが突然変異すると、このような状況が発生します。典型的な例は、スレッドが他のスレッドと対話して共有対象となるが、単一スレッドプログラムでも遠く離れた場所で共有することが容易である。Pythonでは、多くのオブジェクトが、モジュール全体として、またはスタック追跡中、またはクラス属性として多くの場所からアクセスできることを考慮してください。
共有を制限できないなら、可変の制限を考慮するかもしれません。
以下は可変ではない長方形で、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パラメータを用いて,可変でないクラスを容易に作成できた。すべての困難な作品を書く仕事。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")
bが整数のベクトルでないと、何も停止しません。aは一つになるから。
万が一a百万個の元素が長くなりましたか?bは999部をコピーしますか?Pyrsistentには「大O」の性能保証がついています。すべての操作はO(log n)の時間で終わります。また、大きなOを超える性能を向上させるために、任意のC拡張も付属しています。
ネストオブジェクトを修正するために「変換器」という概念が付いています。

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_ブログは可変的でない等価物になります。

'links': 'github' 'twitter'
'posts': 'content': "I'm busy"
'title': 'no updates'
'content': 'pretty busy'
'title': 'still no updates'
'title': 'My blog'
でもブログは同じです。これは、元のオブジェクトを引用しても影響を受けないことを意味します。変換はローカライズ効果だけです。
狂気を分かち合う時、これは役に立ちます。たとえば、デフォルトのパラメータを考慮します。

silly_suma b extrav :
extra extra.extenda b
return extra
この文章では、なぜ不変性が私たちのコードを考えるのに役立つのか、またどのように高価な性能の代償なしに実現されるのかを理解しました。
締め括りをつける
以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考学習価値を持ってほしいです。ありがとうございます。もっと知りたいなら、下のリンクを見てください。