Как заставить локальную область в Python?

В С++ вы можете сделать это, чтобы принудительно использовать локальную область:

{
    int i = 1;
    // Do stuff
}
// local variable i is destroyed
{
    int i = 7;
    // Do more stuff
}

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

Можете ли вы сделать это на Python? Если да, то как?

== UPDATE ==

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

От того, что люди сказали до сих пор, короткий ответ - нет.

(Я понимаю, что есть такие умные способы, как "del", или что это желание иметь блоки может предложить рефакторинг в отдельную функцию в любом случае. Однако я хотел бы подчеркнуть, что это просто короткие фрагменты, в которых вы хотите подчеркнуть переменные в этом маленьком блоке не должны использоваться в другом месте.)

Ответ 1

В Python, если вы объявляете переменную внутри функции, она является локальной и не может быть доступна вне функции

>>> def x():
    i = 5


>>> x()
>>> i

Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    i
NameError: name 'i' is not defined
>>> 

В качестве альтернативы вы можете удалить переменную из пространства имен в конце, чтобы вы не могли ее повторно использовать.

>>> i = 5
>>> del i
>>> i

Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    i
NameError: name 'i' is not defined
>>> 

Ответ 2

Если вам не нравится решение del, вы можете определить определения функций:

def one_function():
    x=0
    def f():
        x = 1
    f()
    print(x) # 0

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

Ответ 3

В С++ вы используете локальную область с скобками {}, чтобы избежать перераспределения переменных или конфликтов имен:

{
    int var=3;
}
{
    float var=1.0f;
}

Пока в python нет явного определения переменной, вы просто назначаете некоторые объекты имени var, когда хотите его использовать, и переписываете одно и то же имя в какую-то новую переменную:

var=3
#do something
var=1.0  #no need to "del var", var refers to a float object now
#do more stuff

Примечание, что использование блока области видимости в С++ может указывать на то, что ваш код должен быть реорганизован на функции или методы, которые можно назвать и использовать повторно. И это то же самое с python.

Ответ 4

У меня был такой же вопрос, и я узнал, что вы абсолютно можете !

Он не такой чистый, как блоки в стиле c, но через две особенности Python мы можем заставить его служить нашим целям.

Причуды:

  1. Какой бы код ни находился внутри класса, он запускается немедленно, даже если этот класс никогда не используется.
  2. Вы можете использовать имя класса столько раз, сколько захотите.

Вот ваш пример:

class DoStuff:
    i = 1
    # Do stuff

# local variable i is destroyed

class DoStuff:
    i = 7
    # Do more stuff
# local variable i is destroyed

Чтобы полностью представить гибкость здесь, посмотрите этот пример. Я назвал класс "Scope", потому что это, вероятно, то, что я бы назвал, чтобы отличить его от других названных классов. Обратите внимание, что "Сфера", конечно, может быть чем угодно.

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

outer = 1

class Scope:
    inner = outer
    print("runs first ---")
    print("outer %d" % outer)
    print("inner %d" % inner)

class Scope:
    inner = outer + 1
    print("runs second ---")
    print("outer %d" % outer)
    print("inner %d" % inner)

print("runs last ---")
print("outer %d" % outer)
print("inner %d" % inner) # This will give an error. Inner does not exist in this scope!

Выход:

runs first ---
outer 1
inner 1
runs second ---
outer 1
inner 2             
runs last ---
outer 1
Traceback (most recent call last):
  File "test.py", line 18, in <module>
    print("inner %d" % inner) # This will give an error. Inner does not exist in this scope!
NameError: name 'inner' is not defined

Так что это выполнимо - давайте взглянем на преимущества/недостатки компромисса.

Выгоды:

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

Недостатки:

  1. Мы используем причуды Python, чтобы заставить это работать, и я чувствую, что сама идея ограничения области действия в отличие от создания новых одноразовых функций не является чем-то, что программисты Python имеют тенденцию делать. Это может вызвать напряженность на рабочем месте или привести к жалобам на использование хака, в отличие от следующих соглашений о создании небольших функций, независимо от того, используется ли что-то более одного раза.
  2. Если вы выходите из проекта, и новые программисты приходят на борт и видят этот код, они, вероятно, сначала будут сбиты с толку. Некоторая документация понадобится для того, чтобы установить ожидания, и необходимо позаботиться о том, чтобы пояснения в документации оставались точными.

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

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

Здесь еще несколько дискуссий вокруг этой конвенции, которую предпочитают Джон Кармак, Джонатан Блоу и Кейси Муратори.

https://news.ycombinator.com/item?id=12120752