Ste*_*202 66
Python中没有"最终"等价物.
但是,要创建类实例的只读字段,可以使用属性函数.
编辑:也许你想要这样的东西:
class WriteOnceReadWhenever:
def __setattr__(self, attr, value):
if hasattr(self, attr):
raise Exception("Attempting to alter read-only value")
self.__dict__[attr] = value
Run Code Online (Sandbox Code Playgroud)
Eli*_*ght 59
在Java中使用变量final
基本上意味着一旦分配给变量,就不能重新分配该变量以指向另一个对象.它实际上并不意味着无法修改对象.例如,以下Java代码运行良好:
public final List<String> messages = new LinkedList<String>();
public void addMessage()
{
messages.add("Hello World!"); // this mutates the messages list
}
Run Code Online (Sandbox Code Playgroud)
但以下甚至不会编译:
public final List<String> messages = new LinkedList<String>();
public void changeMessages()
{
messages = new ArrayList<String>(); // can't change a final variable
}
Run Code Online (Sandbox Code Playgroud)
所以你的问题是关于final
Python中是否存在.它不是.
但是,Python确实具有不可变的数据结构.例如,虽然你可以改变a list
,但你不能改变a tuple
.你可以改变一个set
但不是一个frozenset
等等.
我的建议是不要担心在语言层面强制执行非变异,只需集中精力确保在分配这些对象后不要编写任何改变这些对象的代码.
con*_*gus 40
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
Run Code Online (Sandbox Code Playgroud)
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__
Run Code Online (Sandbox Code Playgroud)
请注意,与其他类型提示一样,这些提示不会阻止您覆盖类型,但它们确实有助于 linter 或 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
Run Code Online (Sandbox Code Playgroud)
这很笨重,但它会在运行时检测到设计问题.
哪有这回事.一般来说,Python的态度是"如果你不想修改它,就不要修改它".无论如何,API的客户不太可能只是在你的无证内部.
我想,你可以通过对模型的相关位使用元组或命名元组来解决这个问题,这些位本质上是不可变的.这仍然无助于您的模型的任何部分当然必须是可变的.
您可以通过描述符协议模拟类似的东西,因为它允许以您希望的方式定义读取和设置变量.
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
Run Code Online (Sandbox Code Playgroud)
截至 2019 年和PEP 591,Python 有一个Final
类型。在 Python 3.8 发布之前,它不会在标准库中可用,但在那之前您可以通过typing-extensions库使用它。final
尽管 Python 仍然是一种动态类型语言,但它不会像在 Java 中那样工作。但是如果你将它与像mypy这样的静态类型检查器一起使用,它会给你带来非常相似的好处。
还有一个final
装饰器可用于将类方法标记为 final 并防止被覆盖。同样,这仅在“编译时”进行检查,因此您需要在工作流程中包含静态类型检查器。