`final`关键字相当于Python中的变量?
题
我在Python中找不到相当于Java的 final
的文档,有这样的事吗?
我正在创建一个对象的快照(如果有任何失败则用于恢复);一旦分配了这个备份变量,就不应该修改它 - Python中的类似最终功能对此很有用。
解决方案
在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
}
所以你的问题是关于Python中是否存在 final
。它没有。
但是,Python确实有不可变的数据结构。例如,虽然您可以改变 list
,但您不能改变元组
。你可以改变 set
而不是 frozenset
等。
我的建议是不要担心在语言层面强制执行非变异,而只是集中精力确保在分配这些对象后不要编写任何改变这些对象的代码。
其他提示
Python中没有“最终”等价物。
但是,要创建类实例的只读字段,可以使用财产功能。
编辑:也许你想要这样的东西:
class WriteOnceReadWhenever:
def __setattr__(self, attr, value):
if hasattr(self, attr):
raise Exception("Attempting to alter read-only value")
self.__dict__[attr] = value
一次性赋值变量是一个设计问题。您可以设置应用程序,使变量只设置一次。
但是,如果您想要对设计进行运行时检查,可以使用对象周围的包装器来完成。
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”。它没有“公共”的和“受保护的”或者,除了命名约定。这不是“束缚和纪律”。
您可以通过描述符协议,因为它允许以您希望的方式定义读数和设置变量。
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
来验证变量是否设置为您最初设置为&#的目的? 8211;如果你愿意,请仔细检查。虽然这与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类型,所以我建议使用描述符来创建最终类型:
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"