ключевое слово `final` эквивалентно переменным в Python?

StackOverflow https://stackoverflow.com/questions/802578

  •  03-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

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

Другие советы

В Python нет `окончательного" эквивалента.

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

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

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

        self.__dict__[attr] = value

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

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

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

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

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

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

Python не имеет эквивалента термина "final".В нем также нет слов "общедоступный" и "защищенный", за исключением соглашения об именовании.Дело не в том, что "рабство и дисциплина".

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

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

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

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

Хотя это старый вопрос, я решил добавить еще один потенциальный вариант:Вы также можете использовать 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 блок, вероятно, был бы разумным дополнением.Как бы то ни было, это может пригодиться в зависимости от вашей ситуации.

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

Некоторые из других ответов здесь делают классы полными псевдофинальных переменных, и я предпочитаю, чтобы в моем классе было только несколько конечных типов, поэтому я предлагаю использовать дескриптор для создания конечного типа:

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"
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top