PythonでJavaのfinal
に相当するものに関するドキュメントが見つかりませんでした。そのようなことはありますか?
オブジェクトのスナップショットを作成しています(何かが失敗した場合の復元に使用されます)。このバックアップ変数が割り当てられたら、変更しないでください-Pythonの最後のような機能はこのために良いでしょう。
Java be 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
}
あなたの質問は、Pythonにfinal
が存在するかどうかです。ありません。
ただし、Pythonには不変のデータ構造があります。たとえば、list
を変更することはできますが、Tuple
を変更することはできません。 set
、ただしfrozenset
などではない.
私のアドバイスは、言語レベルで非変異を強制することを心配せず、割り当てられた後にこれらのオブジェクトを変異させるコードを書かないようにすることに集中することです。
Pythonには「最終」に相当するものはありません。
ただし、クラスインスタンスの読み取り専用フィールドを作成するには、 property 関数を使用できます。
Edit:おそらく次のようなものが欲しいでしょう:
class WriteOnceReadWhenever:
def __setattr__(self, attr, value):
if hasattr(self, attr):
raise Exception("Attempting to alter read-only value")
self.__dict__[attr] = value
1回割り当て変数は設計上の問題です。変数が一度だけ設定されるようにアプリケーションを設計します。
ただし、設計の実行時チェックが必要な場合は、オブジェクトのラッパーを使用して実行できます。
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には「最終」に相当するものはありません。命名規則を除き、「パブリック」と「保護」もありません。それはその「束縛と規律」ではありません。
descriptor protocol を使用して、そのような何かをシミュレートできます。これは、変数の読み取りと設定を希望どおりに定義できるためです。
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
http://code.activestate.com/recipes/576527/ はフリーズ機能を定義しますが、完全には機能しません。
しかし、それを変更可能のままにすることを検討します。
これは古い質問ですが、さらに別の潜在的なオプションを追加することを考えました: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
ブロックはおそらく賢明な追加です。とにかく、あなたの状況に応じて便利になるかもしれません。
Pythonには確かにfinal型はありません。タプルなどの不変型がありますが、それは別のものです。
ここの他の回答のいくつかは、クラスを疑似最終変数でいっぱいにしますが、私のクラスにはいくつかの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"
2019および PEP 591 の時点で、PythonにはFinal
タイプがあります。 Python 3.8のリリースまで標準ライブラリでは使用できませんが、それまでは、type-extensionsライブラリを介して使用できます。 Javaは依然として動的に型付けされた言語ですが、Pythonの最終的な作品としては機能しません。しかし、 mypy のような静的型チェッカーと一緒に使用すると、非常によく似た利点が得られます。
クラスメソッドをfinalとしてマークし、オーバーライドされないようにするために適用できるfinal
デコレータもあります。繰り返しますが、これは「コンパイル時」にのみチェックされるため、ワークフローに静的型チェッカーを含める必要があります。