Java Python中变量的`final`关键字等效吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/802578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:38:17  来源:igfitidea点击:

`final` keyword equivalent for variables in Python?

javapythonkeywordfinal

提问by Jason Coon

I couldn't find documentation on an equivalent of Java's finalin Python, is there such a thing?

final在 Python 中找不到与 Java 等效的文档,有这样的东西吗?

I'm creating a snapshot of an object (used for restoration if anything fails); once this backup variable is assigned, it should not be modified -- a final-like feature in Python would be nice for this.

我正在创建一个对象的快照(用于在出现任何故障时进行恢复);一旦分配了这个备份变量,就不应该修改它——Python 中的一个类似 final 的特性会很好。

采纳答案by Eli Courtwright

Having a variable in Java be finalbasically means that once you assign to a variable, you may not reassign that variable to point to another object. It actually doesn't mean that the object can't be modified. For example, the following Java code works perfectly well:

在 Java 中拥有一个变量final基本上意味着一旦您分配给一个变量,您就不能重新分配该变量以指向另一个对象。这实际上并不意味着不能修改对象。例如,以下 Java 代码运行良好:

public final List<String> messages = new LinkedList<String>();

public void addMessage()
{
    messages.add("Hello World!");  // this mutates the messages list
}

but the following wouldn't even compile:

但以下内容甚至无法编译:

public final List<String> messages = new LinkedList<String>();

public void changeMessages()
{
    messages = new ArrayList<String>();  // can't change a final variable
}

So your question is about whether finalexists in Python. It does not.

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

However, Python does have immutable data structures. For example, while you can mutate a list, you can't mutate a tuple. You can mutate a setbut not a frozenset, etc.

但是,Python 确实具有不可变的数据结构。例如,虽然你可以改变 a list,但你不能改变 a tuple。你可以改变 aset但不能改变 afrozenset等。

My advice would be to just not worry about enforcing non-mutation at the language level and simply concentrate on making sure that you don't write any code which mutates these objects after they're assigned.

我的建议是不要担心在语言级别强制执行非突变,只需专注于确保您不会编写任何在分配这些对象后对其进行突变的代码。

回答by RichieHindle

Python has no equivalent of "final". It doesn't have "public" and "protected" either, except by naming convention. It's not that "bondage and discipline".

Python 没有“final”的等价物。除了命名约定外,它也没有“公共”和“受保护”。这不是“束缚和纪律”。

回答by millimoose

There is no such thing. In general, the Python attitude is "if you don't want this modified, just don't modify it". Clients of an API are unlikely to just poke around your undocumented internals anyway.

哪有这回事。一般来说,Python 的态度是“如果你不想修改这个,就不要修改它”。无论如何,API 的客户端不太可能只是探查您未记录的内部结构。

You could, I suppose, work around this by using tuples or namedtuples for the relevant bits of your model, which are inherently immutable. That still doesn't help with any part of your model that has to be mutable of course.

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

回答by cobbal

http://code.activestate.com/recipes/576527/defines a freeze function, although it doesn't work perfectly.

http://code.activestate.com/recipes/576527/定义了一个冻结功能,尽管它不能完美地工作。

I would consider just leaving it mutable though.

不过,我会考虑让它可变。

回答by Stephan202

There is no finalequivalent in Python. 

finalPython 中没有等价物。 

But, to create read-only fields of class instances, you can use the propertyfunction.

但是,要创建类实例的只读字段,您可以使用property函数。

Edit: perhaps you want something like this:

编辑:也许你想要这样的东西:

class WriteOnceReadWhenever:
    def __setattr__(self, attr, value):
        if hasattr(self, attr):
            raise Exception("Attempting to alter read-only value")

        self.__dict__[attr] = value

回答by S.Lott

An assign-once variable is a design issue. You design your application in a way that the variable is set once and once only.

一次赋值变量是一个设计问题。您设计应用程序的方式是变量设置一次又一次。

However, if you want run-time checking of your design, you can do it with a wrapper around the object.

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

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

That's clunky, but it will detect design problems at run time.

这很笨拙,但它会在运行时检测设计问题。

回答by UncleZeiv

you can simulate something like that through the descriptor protocol, since it allows to define reading and setting a variable the way you wish.

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

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

回答by John the King

Although this is an old question, I figured I would add yet another potential option: You can also use assertto verify a variable is set to what you originally intended it to be set to – a double checking if you will. Although this is not the same as finalin Java, it can be used to create a similar effect:

虽然这是一个老问题,但我想我会添加另一个可能的选项:您还可以使用assert来验证变量是否设置为您最初想要设置的值——如果您愿意,请进行双重检查。虽然这和finalJava 中的不一样,但可以用来创建类似的效果:

PI = 3.14
radius = 3

try:
    assert PI == 3.14
    print PI * radius**2
except AssertionError:
    print "Yikes."

As seen above, if PIwere for some reason not set to 3.14, an AssertionErrorwould be thrown, so a try/exceptblock would probably be a wise addition. Regardless, it may come in handy depending on your situation.

如上所见,如果PI由于某种原因未设置为3.14AssertionError则将抛出an ,因此try/except块可能是明智的添加。无论如何,它可能会派上用场,具体取决于您的情况。

回答by user2799096

Python indeed does not have a final type, it does have immutable types such as tuples but that is something else.

Python 确实没有最终类型,它确实有不可变类型,例如元组,但那是另外一回事。

Some of the other Answers here make classes full of pseudo final variables and I prefer my class to only have a few Final types, so I suggest using an descriptor to create the final type:

这里的其他一些答案使类充满了伪最终变量,我更喜欢我的类只有几个 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")

If you use this class like so:

如果你像这样使用这个类:

class SomeJob:
    FAILED = FinalProperty[str]("Failed")

Then you will not be able to set that variable in any instance of that class. Unfortunately as with the WriteOnceReadWhenever answer you can still set the class variable.

那么您将无法在该类的任何实例中设置该变量。不幸的是,与 WriteOnceReadWhenever 答案一样,您仍然可以设置类变量。

job = SomeJob()
job.FAILED = "Error, this will trigger the ValueError"
SomeJob.FAILED = "However this still works and breaks the protection afterwards"

回答by antonagestam

As of 2019 and PEP 591, Python has a Finaltype. It won't be available in the standard library until the release of Python 3.8, but until then you can use it via the typing-extensionslibrary. It won't work as finalworks in Java though as Python is still a dynamically typed language. But if you use it together with a static type checker like mypyit will give you very similar benefits.

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

There is also a finaldecorator that can be applied to mark class methods as final and preventing from being overridden. Again this is only checked at "compile-time", so you'd need to include a static type checker in your workflow.

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