Подтвердить что ты не робот

"final" ключевое слово для переменных в Python?

Я не мог найти документацию по эквиваленту Java final в Python, есть ли такая вещь?

Я создаю моментальный снимок объекта (используется для восстановления, если что-то не удается); как только эта резервная переменная назначается, она не должна быть изменена - для этого было бы приятной финал в Python.

4b9b3361

Ответ 1

Наличие переменной в 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
}

Итак, ваш вопрос о том, существует ли final в Python. Это не так.

Однако Python имеет неизменные структуры данных. Например, хотя вы можете мутировать list, вы не можете мутировать tuple. Вы можете мутировать set, но не frozenset и т.д.

Мой совет будет состоять в том, чтобы просто не беспокоиться о том, чтобы обеспечить не-мутацию на уровне языка и просто сосредоточиться на том, чтобы не писать код, который мутирует эти объекты после их назначения.

Ответ 2

В Python нет эквивалента `` final ''.

Но для создания полей только для чтения экземпляров класса вы можете использовать функцию property.

Изменить: возможно, вы хотите что-то вроде этого:

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

        self.__dict__[attr] = value

Ответ 3

Переменная-один раз является проблемой дизайна. Вы разрабатываете свое приложение таким образом, чтобы переменная была установлена ​​один раз и один раз.

Однако, если вам нужна проверка времени выполнения во время выполнения, вы можете сделать это с помощью обертки вокруг объекта.

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

Это неудобно, но будет обнаруживать проблемы проектирования во время выполнения.

Ответ 4

Нет такой вещи. В общем, отношение Python - "если вы не хотите, чтобы это было изменено, просто не изменяйте его". Клиенты API вряд ли просто будут ткнуть вокруг ваших недокументированных внутренних компонентов.

Вы могли бы, я полагаю, обойти это, используя кортежи или namedtuples для соответствующих битов вашей модели, которые по своей сути неизменяемы. Это все равно не помогает с какой-либо частью вашей модели, которая должна быть изменчивой, конечно.

Ответ 5

У Python нет эквивалента "final". Он не имеет "общедоступных" и "защищенных", кроме как по соглашению об именах. Это не то, что "рабство и дисциплина".

Ответ 6

вы можете имитировать что-то подобное через протокол дескриптора, поскольку он позволяет определять чтение и настройку переменной так, как вы пожелаете.

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

Ответ 7

http://code.activestate.com/recipes/576527/ определяет функцию замораживания, хотя она не работает отлично.

Я хотел бы просто оставить его изменчивым, хотя.

Ответ 8

Начиная с 2019 года и PEP 591, Python имеет тип Final. Он не будет доступен в стандартной библиотеке до выхода Python 3.8, но до тех пор вы можете использовать его через библиотеку typing-extensions. Это не будет работать, так как final работает в Java, хотя Python по-прежнему динамически типизированный язык. Но если вы используете его вместе со статическим средством проверки типов, таким как mypy, это даст вам очень похожие преимущества.

Существует также декоратор final, который можно применять для пометки методов класса как окончательных и предотвращающих их переопределение. Опять же, это проверяется только во время компиляции, поэтому вам нужно будет включить проверку статического типа в ваш рабочий процесс.

Ответ 9

Хотя это старый вопрос, я подумал, что добавлю еще один потенциальный вариант: вы также можете использовать assert для проверки того, что переменная установлена ​​в соответствии с тем, что вы изначально предполагали для нее, - двойная проверка, если вы, Хотя это не то же самое, что и final в Java, его можно использовать для создания аналогичного эффекта:

PI = 3.14
radius = 3

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

Как видно выше, если PI по какой-то причине не установлено в 3.14, будет выбрано AssertionError, поэтому блок try/except, вероятно, будет мудрым дополнением. Несмотря на это, это может пригодиться в зависимости от вашей ситуации.

Ответ 10

У 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"

Ответ 11

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__