global и return

Вы, вероятно, встречали функции с ключевым словом return в конце. Знаете что оно означает? В целом то же самое что и в других языках. Давайте посмотрим на эту маленькую функцию:

def add(value1, value2):
    return value1 + value2

result = add(3, 5)
print(result)
# Вывод: 8

Функция выше принимает два значения и возвращает их сумму. Мы также можем переписать её таким образом:

def add(value1,value2):
    global result
    result = value1 + value2

add(3, 5)
print(result)
# Вывод: 8

Как несложно заметить, мы используем глобальную переменную result. Что это означает? К глобальным переменным можно обращаться в том числе и извне области видимости функции. Позвольте продемонстрировать это следующим примером:

# Сначала без глобальной переменной
def add(value1, value2):
    result = value1 + value2

add(2, 4)
print(result)

# Вот чёрт, мы наткнулись на исключение. Но почему?
# Интерпретатор Python говорит нам, что не существует
# переменной с именем result. Так произошло, поскольку
# переменная result доступна исключительно из функции,
# где она была определена, если переменная не является
# глобальной.
Traceback (most recent call last):
  File "", line 1, in
    result
NameError: name 'result' is not defined

# Попробуем исправить код, сделав result глобальной
# переменной
def add(value1, value2):
    global result
    result = value1 + value2

add(2, 4)
print(result)
# Вывод: 6

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

Возврат нескольких значений

Что если мы хотим вернуть две переменные из функции вместо одной? Есть несколько способов, которыми пользуются начинающие разработчики. Первый из них - это использование глобальных переменных. Вот подходящий пример:

def profile():
    global name
    global age
    name = "Danny"
    age = 30

profile()
print(name)
# Вывод: Danny

print(age)
# Вывод: 30

Примечание: как я уже писал, данный метод использовать не рекомендуется. Повторяю, не используйте вышеуказанный метод!

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

def profile():
    name = "Danny"
    age = 30
    return (name, age)

profile_data = profile()
print(profile_data[0])
# Вывод: Danny

print(profile_data[1])
# Вывод: 30

Или общепринятое сокращение:

def profile():
    name = "Danny"
    age = 30
    return name, age

profile_name, profile_age = profile()
print(profile_name)
# Вывод: Danny

print(profile_age)
# Вывод: 30

Не забывайте - в примере выше возвращается кортеж (несмотря на отсутствие скобок), а не отдельные значения. Если вы хотите пойти на один шаг дальше, то попробуйте использовать namedtuple. Пример:

from collection import namedtuple

def profile():
    Person = namedtuple('Person', 'name age')
    return Person(name="Danny", age=31)

# Использование как namedtuple
p = profile()
print(p, type(p))
# Person(name='Danny', age=31) <class '__main__.Person'>
print(p.name)
# Danny
print(p.age)
# 31

# Использование как простого кортежа
p = profile()
print(p[0])
# Danny
print(p[1])
# 31

# Немедленная распаковка
name, age = profile()
print(name)
# Danny
print(age)
# 31

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

Last updated