`final`关键字相当于Python中的变量?

Jas*_*oon 52 python java final keyword

我找不到finalPython中相当于Java的文档,有这样的东西吗?

我正在创建一个对象的快照(如果有任何失败则用于恢复); 一旦分配了这个备份变量,它就不应该被修改 - Python中的类似最终功能对此非常有用.

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)

  • 您可能想更新您的答案,因为它已在 Python 3.8 中引入:https://docs.python.org/3.8/library/typing.html?highlight=final#typing.final (3认同)

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)

所以你的问题是关于finalPython中是否存在.它不是.

但是,Python确实具有不可变的数据结构.例如,虽然你可以改变a list,但你不能改变a tuple.你可以改变一个set但不是一个frozenset等等.

我的建议是不要担心在语言层面强制执行非变异,只需集中精力确保在分配这些对象后不要编写任何改变这些对象的代码.

  • 在Java中,非原始变量指向对象.将变量指定为final意味着您不能使变量指向不同的对象,但是指向的对象可以变异. (4认同)
  • 我发现建议“仅专注于确保在分配这些对象后不要编写任何使这些对象发生变异的代码”是一个可怕的建议。您将如何与他人交流?还是为了自己的未来?有评论或文档字符串?正式的语言结构比注释要容易得多。缺少此功能的Python确实令人担忧。 (2认同)

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 警告您不正确的类型使用。

  • 我同意@antonagestam 的评论。`@typing.final` 仅由静态类型检查器使用。答案应该更清楚地表明,执行脚本时这个装饰器被完全忽略。动态创建的类将默默地忽略此装饰器。 (5认同)
  • 我认为这个答案具有误导性,因为很容易给人一种印象,即最终限定符将阻止人们在运行时重新分配或覆盖,但事实并非如此。 (4认同)
  • @momo就像关于私有属性的问题应该有一个答案来解释Python中没有什么是真正私有的,我认为建议使用`final`/`Final` *限定符*这个问题的答案应该解释它们在运行。请注意,我也回答了这个问题。 (3认同)

S.L*_*ott 9

一次性赋值变量是一个设计问题.您可以设置应用程序,使变量只设置一次.

但是,如果您想要对设计进行运行时检查,则可以使用对象周围的包装器来完成.

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)

这很笨重,但它会在运行时检测到设计问题.


mil*_*ose 7

哪有这回事.一般来说,Python的态度是"如果你不想修改它,就不要修改它".无论如何,API的客户不太可能只是在你的无证内部.

我想,你可以通过对模型的相关位使用元组或命名元组来解决这个问题,这些位本质上是不可变的.这仍然无助于您的模型的任何部分当然必须是可变的.

  • 许多其他类也是不可变的:字符串,整数,长整数,浮点数. (2认同)

Ric*_*dle 6

Python没有"最终"的等价物.除了命名约定外,它也没有"公共"和"受保护".这不是"束缚和纪律".


Unc*_*eiv 5

您可以通过描述符协议模拟类似的东西,因为它允许以您希望的方式定义读取和设置变量.

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)


ant*_*tam 5

截至 2019 年和PEP 591,Python 有一个Final类型。在 Python 3.8 发布之前,它不会在标准库中可用,但在那之前您可以通过typing-extensions库使用它。final尽管 Python 仍然是一种动态类型语言,但它不会像在 Java 中那样工作。但是如果你将它与像mypy这样的静态类型检查器一起使用,它会给你带来非常相似的好处。

还有一个final装饰器可用于将类方法标记为 final 并防止被覆盖。同样,这仅在“编译时”进行检查,因此您需要在工作流程中包含静态类型检查器。