Видимость переменных. Видимость переменных. Видимость переменных.

Видимость переменных.

Open in new window

# Область видимости переменных.

Глобальные и локальные переменные

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

Эти области называются namespace (пространство имен) и существуют во всех языках программирования.

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

Давайте взглянем на следующую функцию:

def f(): 
    print s 
s = "I hate spam"
f()

Переменная s определена как строковая перед тем как мы вызываем функцию f().

Так как внутри функции переменная s не определена, будет использоваться переменная, определенная в глобальном пространстве - вне всяких функций.

Вопрос — а что если определить переменную s внутри функции?

def f(): 
    s = "Me too."
    print s

s = "I hate spam." 
f()
print s

Вывод будет следующий:

Me too.
I hate spam.

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

Что если мы скомбинируем эти два подхода следующим образом:

def f(): 
    print s
    s = "Me too."
    print s


s = "I hate spam." 
f()
print s

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

В результате получаем исключение вида:

UnboundLocalError: local variable 's' referenced before assignment

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

Любая переменная, которая изменяется или создается внутри функции — локальная, если она явно не определена как глобальная при помощи ключевого слова global.

Пример использования global.

def f():
    global s
    print s
    s = "That's clear."
    print s


s = "Python is great!" 
f()
print s

Теперь у нас отсутствует неопределенность и вывод будет следующим:

Python is great!
That's clear.
That's clear.

Локальные переменные или функции не могут быть получены извне, например так:

def f():
    s = "I am globally not known"
    print s

f()
print s

Этот код вызовет такое исключение:

Traceback (most recent call last):
  File "global_local3.py", line 6, in <module>
    print s
NameError: name 's' is not defined

Проверка на существование переменной в локальной или глобальной области видимости.

Как проверить факт существования переменной или функции?

Для этого существуют функции globals() и locals(), которые возвратят список всех переменных в соответствующей области.

if 'myVar' in locals():
    print «myVar exists».


if 'myVar' in globals():
    # myVar exists.

Проверка на существование аттрибута объекта:

if hasattr(obj, 'attr_name'):
    print „obj.attr_name exists“.

Получение аттрибута.

m =  getattr(c, "say", None)

Проверка является ли аттрибут методом.

m =  getattr(c, "say", None)
if callable(m):
    print 'Say is the function!!!'

Пространсто имен (namespace) — это, по сути, коллекция всех имен переменных. Все встроенные в Python функции находятся в глобальном пространстве программы, и поэтому доступны из любой ее точки. Каждый модуль (файл) создает свое собственное глобальное пространство а каждая функция в модуле создает свое локальное. Таким образом в ходе выполнения программы мы имеем множество пространств имен абсолютно изолированных друг от друга. На первом месте идет встроенное глобальное пространство интерпретатора Python? От куда переменные доступны из любого места. Потом пространство модуля, и наконец пространство функций. Каждое пространсво описывается понятием scope. Scope — эта область, выделяемая программной сущьностью (модулем, функцией, методом и т. д.) для хранения переменных. При определении вложенных функций, например:

def outer_function():
    b = 20
    def inner_func():
        c = 30

Для каждой из них будет определен свой scope. Совокупность scopе-ов имеет иерархию (вложенность). При попытке получить доступ к той или иной переменной или функции, интерпретатор осуществляет поиск по scope-ам начиная от наиболее локального пространства по отношению места, из которого осуществляется доступ и кончая глобальным пространствам интерпретатора.

Пример ниже демонстрирует этот принцип:

def outer_function():
    a = 20
    def inner_function():
        a = 30
        print('a =',a)

    inner_function()
    print('a =',a)

a = 10
outer_function()
print('a =',a)

Вывод:

a = 30
a = 20
a = 10

Other topics