final
PythonでJavaに相当するドキュメントを見つけることができませんでしたが、そのようなものはありますか?
オブジェクトのスナップショットを作成しています(何かが失敗した場合の復元に使用されます)。このバックアップ変数が割り当てられたら、変更しないでください。Pythonのfinalのような機能がこれに適しています。
final
Pythonには同等 のものはありません。
ただし、クラスインスタンスの読み取り専用フィールドを作成するには、プロパティ関数を使用できます。
編集:おそらくあなたはこのようなものが欲しいです:
class WriteOnceReadWhenever:
def __setattr__(self, attr, value):
if hasattr(self, attr):
raise Exception("Attempting to alter read-only value")
self.__dict__[attr] = value
Javaに変数があるfinal
ということは、基本的に、変数に割り当てた後は、その変数を別のオブジェクトを指すように再割り当てできないことを意味します。実際には、オブジェクトを変更できないという意味ではありません。たとえば、次のJavaコードは完全に機能します。
public final List<String> messages = new LinkedList<String>();
public void addMessage()
{
messages.add("Hello World!"); // this mutates the messages list
}
しかし、以下はコンパイルすらしません:
public final List<String> messages = new LinkedList<String>();
public void changeMessages()
{
messages = new ArrayList<String>(); // can't change a final variable
}
だからあなたの質問はfinal
Pythonに存在するかどうかについてです。そうではありません。
ただし、Pythonには不変のデータ構造があります。たとえば、を変更することはできますがlist
、を変更することはできませんtuple
。変更することはできますが、変更することはできset
ませんfrozenset
。
私のアドバイスは、言語レベルで非変更を強制することを心配せず、割り当てられた後にこれらのオブジェクトを変更するコードを記述しないようにすることに集中することです。
Python 3.8 ( PEP 591経由)はFinal
、変数、関数、メソッド、およびクラスを追加します。これを使用するいくつかの方法があります:
@final
デコレータ(クラス、メソッド)
from typing import final
@final
class Base:
# Cannot inherit from Base
class Base:
@final
def foo(self):
# Cannot override foo in subclass
Final
注釈
from typing import Final
PI: Final[float] = 3.14159 # Cannot set PI to another value
KM_IN_MILES: Final = 0.621371 # Type annotation is optional
class Foo:
def __init__(self):
self.bar: Final = "baz" # Final instance attributes only allowed in __init__
他のタイピングのヒントと同様に、これらはタイプのオーバーライドを妨げるものではありませんが、リンターやIDEがタイプの誤った使用法について警告するのに役立ちます。
一度割り当て変数は設計上の問題です。変数が一度だけ設定されるようにアプリケーションを設計します。
ただし、デザインの実行時チェックが必要な場合は、オブジェクトのラッパーを使用してチェックできます。
class OnePingOnlyPleaseVassily(object):
def __init__(self):
self.value = None
def set(self, value):
if self.value is not None:
raise Exception("Already set.")
self.value = value
someStateMemo = OnePingOnlyPleaseVassily()
someStateMemo.set(aValue) # works
someStateMemo.set(aValue) # fails
これは不格好ですが、実行時に設計上の問題を検出します。
そのような事はありません。一般に、Pythonの態度は、「これを変更したくない場合は、変更しないでください」です。APIのクライアントは、とにかく文書化されていない内部をただ突っ込む可能性は低いです。
本質的に不変であるモデルの関連ビットにタプルまたは名前付きタプルを使用することで、これを回避できると思います。もちろん、それでもモデルの変更可能である必要のある部分には役立ちません。
Pythonには「final」に相当するものはありません。命名規則を除いて、「public」と「protected」もありません。それは「束縛と規律」ではありません。
記述子プロトコルを介してそのようなものをシミュレートできます。これにより、変数の読み取りと設定を希望どおりに定義できます。
class Foo(object):
@property
def myvar(self):
# return value here
@myvar.setter
def myvar(self, newvalue):
# do nothing if some condition is met
a = Foo()
print a.myvar
a.myvar = 5 # does nothing if you don't want to
2019年およびPEP591の時点で、PythonにはFinal
タイプがあります。Python 3.8がリリースされるまで標準ライブラリでは利用できませんが、それまでは、typeing-extensionsライブラリを介して使用できます。final
Pythonはまだ動的に型付けされた言語であるため、Javaでは機能しません。しかし、 mypyのような静的タイプチェッカーと一緒に使用すると、非常によく似た利点が得られます。
final
クラスメソッドをfinalとしてマークし、オーバーライドされないようにするために適用できるデコレータもあります。繰り返しますが、これは「コンパイル時」にのみチェックされるため、ワークフローに静的型チェッカーを含める必要があります。
http://code.activestate.com/recipes/576527/はフリーズ機能を定義していますが、完全には機能しません。
ただし、変更可能のままにしておくことを検討します。
Pythonには確かに最終的な型がなく、タプルなどの不変の型がありますが、それは別のものです。
ここにある他の回答のいくつかは、クラスを疑似最終変数でいっぱいにします。クラスにはいくつかのFinal型しか持たない方がよいので、記述子を使用して最終型を作成することをお勧めします。
from typing import TypeVar, Generic, Type
T = TypeVar('T')
class FinalProperty(Generic[T]):
def __init__(self, value: T):
self.__value = value
def __get__(self, instance: Type, owner) -> T:
return self.__value
def __set__(self, instance: Type, value: T) -> None:
raise ValueError("Final types can't be set")
このクラスを次のように使用する場合:
class SomeJob:
FAILED = FinalProperty[str]("Failed")
そうすると、そのクラスのどのインスタンスでもその変数を設定できなくなります。残念ながら、WriteOnceReadWheneverの回答と同様に、クラス変数を設定できます。
job = SomeJob()
job.FAILED = "Error, this will trigger the ValueError"
SomeJob.FAILED = "However this still works and breaks the protection afterwards"
これは古い質問ですが、さらに別の潜在的なオプションを追加することassert
にしました。変数が本来の設定に設定されていることを確認するために使用することもできます。必要に応じて再確認します。これはJavaの場合と同じではありませんがfinal
、同様の効果を作成するために使用できます。
PI = 3.14
radius = 3
try:
assert PI == 3.14
print PI * radius**2
except AssertionError:
print "Yikes."
上記のように、PI
何らかの理由でに設定されていない場合は3.14
、AssertionError
がスローされるため、try/except
ブロックはおそらく賢明な追加になります。とにかく、状況によっては重宝するかもしれません。