Яка область змінної, ініціалізованої в операторі if?


266

Я новачок у Python, тому це, мабуть, просте питання щодо визначення масштабів. Наступний код у файлі (модулі) Python мене трохи бентежить:

if __name__ == '__main__':
    x = 1

print x

В інших мовах, над якими я працював, цей код буде кидати виняток, оскільки xзмінна є локальною для ifоператора і не повинна існувати поза нею. Але цей код виконує і друкує 1. Чи може хтось пояснити цю поведінку? Чи всі змінні, створені в модулі, глобальні / доступні для всього модуля?


17
Ще одна особливість , ви не могли б знати: якщо ifвище твердження не має місця (тобто, __name__це НЕ '__main__' , наприклад , при імпорті модуля замість виконання його верхнього рівня), то xніколи не були пов'язані, і подальше print xзаяву кине а NameError: name 'x' is not defined.
Санта

Відповіді:


301

Змінні Python відносяться до найпотаємнішої функції, класу або модуля, якому вони призначені. Блоки управління, такі як ifі whileблоки, не враховуються, тому змінна, присвоєна всередині if, все ще присвоюється функції, класу або модулю.

(Неявні функції, визначені виразом генератора або розумінням списку / списку / набору / dict , зараховуються так само, як і лямбда-вирази. Ви не можете заповнити оператор присвоєння жодному з них, але параметри лямбда та forцілі пункту - це неявне призначення.)



105

Так, вони знаходяться в тій же "локальній області", і насправді такий код звичайний у Python:

if condition:
  x = 'something'
else:
  x = 'something else'

use(x)

Зауважте, що xвін не оголошується та не ініціалізується перед умовою, як, наприклад, у C або Java.

Іншими словами, Python не має областей блокового рівня. Будьте обережні, але з такими прикладами, як

if False:
    x = 3
print(x)

що явно призвело б до NameErrorвинятку.


42

Область застосування пітона відповідає такому порядку:

  • Шукайте локальну область

  • Шукайте сферу будь-яких функцій, що додаються

  • Шукайте глобальну сферу

  • Шукайте вбудовані модулі

( джерело )

Зауважте, що ifй інші конструкції циклічного / розгалуження не вказані - лише класи, функції та модулі надають сферу застосування в Python, тому все, що оголошено в ifблоці, має таку ж область, як і все, що відхиляється поза блоком. Змінні не перевіряються під час компіляції, тому інші мови кидають виняток. У python до тих пір, поки змінна існує в той час, коли вона вам потрібна, виняток не буде викинуто.


9

Як сказав Елі, Python не потребує оголошення змінної. В С ви б сказали:

int x;
if(something)
    x = 1;
else
    x = 2;

але в Python декларація неявна, тому при призначенні x вона автоматично оголошується. Це тому, що Python динамічно набирається - він не працюватиме статично набраною мовою, тому що залежно від використовуваного шляху може використовуватися змінна без декларування. Це може бути зафіксовано під час компіляції статично набраною мовою, але з динамічно набраною мовою це дозволено.

Єдина причина, що статично набрана мова обмежується тим, що ifчерез цю проблему необхідно оголошувати змінні поза операторами. Прийміть динамічне!


9

На відміну від таких мов, як C, змінна Python має сферу дії для всієї функції (або класу, або модуля), де вона з'являється, а не лише у найпотужнішому "блоці". Це як би ви оголосили int xу верхній частині функції (або класу, або модуля), за винятком того, що в Python вам не потрібно оголошувати змінні.

Зауважте, що існування змінної xперевіряється лише під час виконання - тобто коли ви переходите до print xоператора. Якщо __name__не рівні , "__main__"то ви отримаєте виняток: NameError: name 'x' is not defined.


Класи не створюють сфери; "локальна" змінна в класі просто додається до диктату класу при створенні.
чепнер

3

Так. Це справедливо і для forсфери застосування. Але не функції, звичайно.

У вашому прикладі: якщо умова у ifтвердженні помилкова, xне буде визначено, хоча.


2

ви виконуєте цей код з командного рядка, тому ifумови вірні і xвстановлені. Порівняйте:

>>> if False:
    y = 42


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

0

І зверніть увагу, що оскільки типи Python перевіряються лише під час виконання, ви можете мати код типу:

if True:
    x = 2
    y = 4
else:
    x = "One"
    y = "Two"
print(x + y)

Але у мене виникають проблеми з думкою про інші способи роботи коду без помилок через проблеми типу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.