java-`final`关键字是否等效于Python中的变量?
我找不到与Python上的Java final等效的文档,是否有这样的东西?
我正在创建一个对象的快照(用于在任何失败的情况下用于还原); 一旦分配了此备份变量,就不应对其进行修改-Python中类似final的功能将非常有用。
11个解决方案
65 votes
Python中没有``最终''等效项。
但是,要创建类实例的只读字段,可以使用属性函数。
编辑:也许您想要这样的事情:
class WriteOnceReadWhenever:
def __setattr__(self, attr, value):
if hasattr(self, attr):
raise Exception("Attempting to alter read-only value")
self.__dict__[attr] = value
Stephan202 answered 2020-02-07T02:40:20Z
58 votes
在Java中具有变量list基本上意味着,一旦分配了变量,就不能重新分配该变量以指向另一个对象。 实际上,这并不意味着不能修改该对象。 例如,以下Java代码可以很好地运行:
public final List messages = new LinkedList();
public void addMessage()
{
messages.add("Hello World!"); // this mutates the messages list
}
但是以下代码甚至无法编译:
public final List messages = new LinkedList();
public void changeMessages()
{
messages = new ArrayList(); // can't change a final variable
}
因此,您的问题是关于Python中是否存在list。 它不是。
但是,Python确实具有不可变的数据结构。 例如,虽然可以变异list,但不能变异tuple。可以变异set,但不能变异frozenset,依此类推。
我的建议是,不要担心在语言级别强制执行非突变,而只是专注于确保您没有编写任何在分配了这些对象后对它们进行突变的代码。
Eli Courtwright answered 2020-02-07T02:39:51Z
9 votes
一次分配变量是一个设计问题。 设计应用程序时,只需一次设置变量即可。
但是,如果要对设计进行运行时检查,则可以使用对象周围的包装器进行检查。
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
这很笨拙,但是它将在运行时检测到设计问题。
S.Lott answered 2020-02-07T02:40:50Z
7 votes
哪有这回事。 通常,Python的态度是“如果您不想对此进行修改,就不要对其进行修改”。 无论如何,API的客户不太可能会无所事事。
我想,可以通过对模型的相关位使用元组或namedtuple来解决此问题,这些元组本来就是不可变的。 当然,这对于您模型中必须可变的任何部分仍然没有帮助。
millimoose answered 2020-02-07T02:41:18Z
6 votes
Python没有等效的“ final”。 除了命名约定外,它也没有“公共”和“受保护”。 不是那种“束缚和纪律”。
RichieHindle answered 2020-02-07T02:41:38Z
5 votes
您可以通过描述符协议进行类似的模拟,因为它可以定义读取和设置变量的方式。
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
UncleZeiv answered 2020-02-07T02:42:00Z
3 votes
[http://code.activestate.com/recipes/576527/]定义了冻结功能,尽管它不能完美运行。
我会考虑让它保持可变。
cobbal answered 2020-02-07T02:42:24Z
2 votes
截至2019年和PEP 591,Python具有final类型。 在Python 3.8发行之前,它在标准库中不可用,但是在此之前,您可以通过类型扩展库使用它。 尽管Python仍然是一种动态类型的语言,但是它不能像final在Java中那样工作。 但是,如果将其与mypy等静态类型检查器结合使用,它将为您带来非常相似的好处。
还有一个final装饰器,可用于将类方法标记为final并防止其被覆盖。 同样,这仅在“编译时”进行检查,因此您需要在工作流程中包括静态类型检查器。
antonagestam answered 2020-02-07T02:42:51Z
2 votes
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__
congusbongus answered 2020-02-07T02:46:20Z
0 votes
尽管这是一个古老的问题,但我认为我会添加另一个潜在的选择:您还可以使用PI来验证变量是否设置为您最初希望将其设置的值–仔细检查是否可以。 尽管这与Java中的3.14不同,但可以使用它来产生类似的效果:
PI = 3.14
radius = 3
try:
assert PI == 3.14
print PI * radius**2
except AssertionError:
print "Yikes."
如上所述,如果出于某种原因未将PI设置为3.14,则会抛出AssertionError,因此try/except块可能是明智的选择。 无论如何,根据您的情况,它可能会派上用场。
John the King answered 2020-02-07T02:46:45Z
0 votes
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"
user2799096 answered 2020-02-07T02:47:19Z