kquick 6 / 6 / 5 Регистрация: 15.05.2014 Сообщений: 104 |
||||||||||||
1 |
||||||||||||
27.11.2015, 08:49. Показов 6955. Ответов 9 Метки нет (Все метки)
Предположим есть переменная для хранения чисел типа int. Хотелось бы изменять её внутри функций и затем использовать её в основном модуле. Как это можно просто сделать? Хотелось бы использовать нечто вроде:
Но для примитивного типа это неработает. Можно создать список из одного элемента и с ним работать:
В этом случае теряется читаемость. И вообще, прйдется писать во всех функциях [0]. Можно сделать класс и перегрузить операторы для основных операций:
Может есть какой-то более лучший подход к решению этой проблемы?
__________________
0 |
Vigi 623 / 464 / 178 Регистрация: 28.05.2012 Сообщений: 1,386 |
||||
27.11.2015, 09:10 |
2 |
|||
1 |
0x10 3254 / 2056 / 351 Регистрация: 24.11.2012 Сообщений: 4,909 |
||||
27.11.2015, 10:07 |
3 |
|||
Может есть какой-то более лучший подход к решению этой проблемы? Предположим, что функция inc выбрана исключительно для демонстрации.
1 |
kquick 6 / 6 / 5 Регистрация: 15.05.2014 Сообщений: 104 |
||||||||||||||||
27.11.2015, 10:15 [ТС] |
4 |
|||||||||||||||
Функции не должны ничего знать про название передаваемой переменной. При изменении оной придется изменять все функции, предположим их 1000.
А если хотим, чтобы функция возвращала что-нибудь другое, но при этом изменяла a? Можно, конечно сделать так:
Но это немного нето. Нужно, чтобы функция меняла переменную, и ничего незнала про её название снаружи. Не по теме:
0 |
3254 / 2056 / 351 Регистрация: 24.11.2012 Сообщений: 4,909 |
|
27.11.2015, 10:20 |
5 |
Нужно, чтобы функция меняла переменную, и ничего незнала про её название снаружи. Какая проблема решается? Дай более широкий контекст. Возможно, есть другие выразительные средства для решения задачи. Каждый out-параметр функции — это сайд-эффект. Множество out-параметров усложняют понимание и отладку кода. Лучше пересмотреть такой дизайн.
1 |
dondublon 4606 / 2027 / 359 Регистрация: 17.03.2012 Сообщений: 10,081 Записей в блоге: 6 |
||||||||
27.11.2015, 10:24 |
6 |
|||||||
Глобальные переменные — зло лютое, их нельзя использовать.
Добавлено через 3 минуты
1 |
3254 / 2056 / 351 Регистрация: 24.11.2012 Сообщений: 4,909 |
|
27.11.2015, 10:28 |
7 |
dondublon, оба варианта были в первом посте. Вариант с ctypes похож на создание своей обертки, но использование этой библиотеки — почти наверняка не то, чего хочет автор. Из документации: ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python. Т.к. не была обозначена конкретная задача, я предполагаю, что дергать функции из шареных библиотек автор не собирается. Следовательно, такое использование ctypes можно считать нецелевым и создающим необоснованную зависимость.
1 |
4606 / 2027 / 359 Регистрация: 17.03.2012 Сообщений: 10,081 Записей в блоге: 6 |
|
27.11.2015, 10:34 |
8 |
оба варианта были в первом посте. Да, второй был. Просмотрел. Первого не было.
Вариант с ctypes похож на создание своей обертки, Ну так тут и нужна обёртка, никак не обойдёшь.
Из документации: Я в курсе.
дергать функции из шареных библиотек автор не собирается. Следовательно, такое использование ctypes можно считать нецелевым и создающим необоснованную зависимость. Это стандартная библиотека.
1 |
3254 / 2056 / 351 Регистрация: 24.11.2012 Сообщений: 4,909 |
|
27.11.2015, 10:38 |
9 |
Это стандартная библиотека. Я в курсе.
1 |
dondublon 4606 / 2027 / 359 Регистрация: 17.03.2012 Сообщений: 10,081 Записей в блоге: 6 |
||||||||
27.11.2015, 11:16 |
10 |
|||||||
Ещё вариант.
Добавлено через 12 минут
0 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
27.11.2015, 11:16 |
10 |
Переменная, доступ к которой можно получить из любого места в коде, называется глобальной. Ее можно определить вне блока. Другими словами, глобальная переменная, объявленная вне функции, будет доступна внутри нее.
С другой стороны, переменная, объявленная внутри определенного блока кода, будет видна только внутри этого же блока — она называется локальной.
Разберемся с этими понятиями на примере.
Пример локальных и глобальных переменных
def sum():
a = 10 # локальные переменные
b = 20
c = a + b
print("Сумма:", c)
sum()
Вывод: Сумма: 30
.
Переменная объявлена внутри функции и может использоваться только в ней. Получить доступ к этой локальной функции в других нельзя.
Для решения этой проблемы используются глобальные переменные.
Теперь взгляните на этот пример с глобальными переменными:
a = 20 # определены вне функции
b = 10
def sum():
c = a + b # Использование глобальных переменных
print("Сумма:", c)
def sub():
d = a - b # Использование глобальных переменных
print("Разница:", d)
sum()
sub()
Вывод:
Сумма: 30
Разница: 10
В этом коде были объявлены две глобальные переменные: a
и b
. Они используются внутри функций sum()
и sub()
. Обе возвращают результат при вызове.
Если определить локальную переменную с тем же именем, то приоритет будет у нее. Посмотрите, как в функции msg
это реализовано.
def msg():
m = "Привет, как дела?"
print(m)
msg()
m = "Отлично!" # глобальная переменная
print(m)
Вывод:
Привет, как дела?
Отлично!
Здесь была объявлена локальная переменная с таким же именем, как и у глобальной. Сперва выводится значение локальной, а после этого — глобальной.
Python предлагает ключевое слово global
, которое используется для изменения значения глобальной переменной в функции. Оно нужно для изменения значения. Вот некоторые правила по работе с глобальными переменными.
Правила использования global
- Если значение определено на выходе функции, то оно автоматически станет глобальной переменной.
- Ключевое слово
global
используется для объявления глобальной переменной внутри функции. - Нет необходимости использовать
global
для объявления глобальной переменной вне функции. - Переменные, на которые есть ссылка внутри функции, неявно являются глобальными.
Пример без использования глобального ключевого слова.
c = 10
def mul():
c = c * 10
print(c)
mul()
Вывод:
line 5, in mul
c = c * 10
UnboundLocalError: local variable 'c' referenced before assignment
Этот код вернул ошибку, потому что была предпринята попытка присвоить значение глобальной переменной. Изменять значение можно только с помощью ключевого слова global
.
c = 10
def mul():
global c
c = c * 10
print("Значение в функции:", c)
mul()
print("Значение вне функции:", c)
Вывод:
Значение в функции: 100
Значение вне функции: 100
Здесь переменная c была объявлена в функции mul()
с помощью ключевого слова global
. Ее значение умножается на 10 и становится равным 100. В процессе работы программы можно увидеть, что изменение значения внутри функции отражается на глобальном значении переменной.
Глобальные переменные в модулях Python
Преимущество использования ключевого слова global
— в возможности создавать глобальные переменные и передавать их между модулями. Например, можно создать name.py, который бы состоял из глобальных переменных. Если их изменить, то изменения повлияют на все места, где эти переменные встречаются.
1. Создаем файл name.py для хранения глобальных переменных:
a = 10
b = 20
msg = "Hello World"
2. Создаем файл change.py для изменения переменных:
import name
name.a = 15
name.b = 25
name.msg = "Dood bye"
Меняем значения a
, b
и msg
. Эти переменные были объявлены внутри name
, и для их изменения модуль нужно было импортировать.
3. В третий файл выводим значения измененных глобальных переменных.
import name
import change
print(name.a)
print(name.b)
print(name.msg)
Значение изменилось. Вывод:
15
25
Dood bye
Global во вложенных функциях
Можно использовать ключевое слово global
во вложенных функциях.
def add():
a = 15
def modify():
global a
a = 20
print("Перед изменением:", a)
print("Внесение изменений")
modify()
print("После изменения:", a)
add()
print("Значение a:", a)
Вывод:
Перед изменением: 15
Внесение изменений
После изменения: 15
Значение a: 20
В этом коде значение внутри add()
принимает значение локальной переменной x = 15
. В modify()
оно переназначается и принимает значение 20 благодаря global
. Это и отображается в переменной функции add()
.
Переменная, к которой может получить доступ другой блок, называется глобальной переменной. Его можно определить вне блока. Другими словами, глобальная переменная определяется вне функции, и мы можем получить к ней доступ внутри функции.
С другой стороны, переменная, определенная в блоке и доступная для этого блока, называется локальной переменной. К такой переменной можно получить доступ только в определенном блоке.
Давайте разберемся как создать и объявить глобальную переменную в Python и посмотрим примеры локальной и глобальной переменных.
Пример локальной переменной:
# example of local variable def sum(): a = 10 # local variables b = 20 c = a + b print("the sum is:", c) sum() # function calling
Выход:
The sum is: 30
Объяснение:
Переменная определяется внутри функции и может использоваться только в определенной функции, поэтому природа переменной называется локальной переменной. Мы не можем получить к ним доступ в других функциях.
Чтобы преодолеть эту проблему, мы используем глобальные переменные. Давайте разберемся в примере глобальной переменной.
Пример –
# example of a global variable a = 20 # defined outside the function b = 10 def sum(): c = a + b # Using global variables print("The sum is:", c) def sub(): d = a - b # using global variables print("The sub is:", d) sum() # function calling sub()
Выход:
The sum is: 30 The sub is: 10
Объяснение:
В приведенном выше коде мы определили две глобальные переменные a и b вне функций. Мы использовали их внутри функций sum() и sub(). Обе функции вернули результат при вызове.
Если мы определим локальную переменную с таким же именем, она напечатает значение, которое находится внутри функции, а затем значение глобальной переменной.
Пример 3:
def msg(): m = "Hello, how are you?" print(m) msg() m = "I am fine" # global scope print(m)
Выход:
Hello, how are you? I am fine
Объяснение:
Мы определили локальную переменную с тем же именем, что и глобальная переменная; сначала напечатали локальную переменную, а затем значение глобальной переменной.
Глобальное ключевое слово
Python предоставляет глобальное ключевое слово, которое используется для изменения значения глобальной переменной внутри функции. Это полезно, когда мы хотим изменить значение глобальной переменной или присвоить другое значение. Ниже приведены несколько правил для определения глобальных переменных.
Правила глобальных ключевых слов:
- Если значение определено на выходе функции, оно автоматически станет глобальной переменной или ее областью действия в глобальном масштабе.
- Глобальное ключевое слово используется для объявления глобальной переменной внутри функции.
- Нам не нужно использовать ключевое слово global для объявления глобальной переменной вне функции.
- Переменные, на которые есть ссылка внутри функции, неявно являются глобальными.
Пример – без глобального ключевого слова:
# The example of without using the global keyword c = 10 def mul(): # Multiply by 10 c = c * 10 print(c) mul()
Выход:
line 8, in mul c = c * 10 UnboundLocalError: local variable 'c' referenced before assignment
Объяснение:
В приведенном выше коде возникла ошибка, поскольку мы пытались присвоить значение глобальной переменной. Мы можем изменить значение глобального значения внутри функции, используя ключевое слово global.
Пример – с глобальным ключевым словом:
# The example using the global keyword c = 10 def mul(): global c # Multiply by 10 c = c * 10 print("The value inside function: ", c) mul() print('The value outside the function: ', c)
Выход:
The value inside function: 100 The value outside the function: 100
В приведенном выше примере мы определили переменную c в функции mul() с помощью ключевого слова global. Значение c умножается на 10; следовательно, возвращается 200. Мы видим в выходных данных, что изменение значения внутри функции отражается на значении вне глобальной переменной.
Преимущество ключевого слова global заключается в создании глобальных переменных и совместном использовании их между различными модулями. Например, мы создаем name.py, который состоит из глобальных переменных. Если мы изменим эти переменные, то это изменение отразится повсюду. Давайте разберемся в следующем примере.
Код – 1: Создайте файл name.py для хранения глобальных переменных.
a = 10 b = 20 msg = "Hello World"
Код – 2: Создайте файл change.py для изменения глобальных переменных.
import name name.a = 15 name.b = 26 name.msg = "Welcome to JavaTpoint"
Здесь мы изменили значение a, b и msg. Эти глобальные переменные были определены в файле name.py, и мы импортировали name и получили доступ к этим переменным.
Код – 3: Создайте файл result.py для печати измененных глобальных переменных.
import name import change print(change.a) print(change.b) print(change.msg)
Выход:
15 26 Welcome to JavaTpoint
Ключевое слово global во вложенных функциях
Мы можем использовать ключевое слово global внутри вложенной функции. Мы должны объявить переменную, используя ключевое слово global внутри вложенной функции. Давайте разберемся в следующем примере.
Пример –
# The example of global in nested function def add(): a = 15 def modify(): global a a = 20 print("Before modifying : ", a) print("Making change") modify() print("After modifying: ", a) add() print("value of x: ", a)
Выход:
Before modifying : 15 Making change After modifying: 15 value of x 20
Объяснение:
В приведенном выше коде значение внутри add() принимает значение локальной переменной x = 15. В функции modify() мы присвоили x = 20 с помощью ключевого слова global. Это изменение отражено в переменной функции add().
Изучаю Python вместе с вами, читаю, собираю и записываю информацию опытных программистов.
В процессе нашего обучения мы изучили ряд встроенных в Python функций: print(), input(), max(), min() и другие. Часто в программах требуется использовать какую-то часть кода несколько раз. В таком случае программисты создают функции. Функции помогают использовать написанный код в программах многократно, а также делают код более понятным за счёт деления его на блоки.
Синтаксис создания функции выглядит следующим образом:
def <имя функции>(<аргументы функции>):
<тело функции>
Правила для записи имени функции такие же, как и для переменных: имя может содержать строчные буквы английского алфавита, цифры и знаки подчеркивания. Аргументы функции — это её параметры, которые становятся переменными в теле функции. Тело функции содержит код, который работает с аргументами и внешними переменными, а затем возвращает результат с помощью оператора return
. При возврате значения, функция прекращает свою работу, а интерпретатор продолжает работу программы, подставив на место вызова функции возвращенное значение.
Напишем функцию, которая проверяет, что список целых чисел, передаваемый ей как аргумент, содержит только чётные числа:
def only_even(numbers):
result = True
for x in numbers:
if x % 2 != 0:
result = False
break
return result
print(only_even([2, 4, 6]))
print(only_even([1, 2, 3]))
Вывод программы:
True False
В функциях можно использовать несколько операторов return
. Первый сработавший в теле функции оператор return
остановит выполнение функции и вернёт её значение. Наш пример можно упростить, использовав вместо флага result несколько точек возврата значения:
def only_even(numbers):
for x in numbers:
if x % 2 != 0:
return False
return True
print(only_even([2, 4, 6]))
print(only_even([1, 2, 3]))
Вывод программы:
True False
Обратите внимание: функция в Python всегда возвращает результат, даже если в ней нет return
или присутствует return
без возвращаемого значения. Тогда возвращаемый результат будет None
— специальный тип данных в Python, который дословно можно перевести с английского как «ничего». Например, None
возвращает функция print()
:
print(print("Эту строку выведет функция до возврата значения."))
Вывод программы:
Эту строку выведет функция до возврата значения. None
Из функции можно вернуть сразу несколько значений. Для этого их нужно перечислить через запятую после оператора return
. В программу эти значения вернутся в кортеже. Добавим в нашу функцию дополнительно возврат индекса первого нечётного элемента, который встретится:
def only_even(numbers):
for i, x in enumerate(numbers):
if x % 2 != 0:
return False, i
return True
print(only_even([2, 4, 6]))
print(only_even([1, 2, 3]))
Вывод программы:
True (False, 0)
Обратите внимание, что в одном случае мы возвращаем значение логического типа, в другом — кортеж. Тогда в программе нужно будет дополнительно проверять, значение какого типа вернёт функция, так как от этого зависит набор операций и методов, доступных для этого типа данных.
Итак, функции могут работать с аргументами и возвращать значения. Значение аргумента доступно только внутри функции. Покажем это на примере:
def only_even(numbers):
for i, x in enumerate(numbers):
if x % 2 != 0:
return False, i
return True
print(numbers)
Вывод программы:
NameError: name 'numbers' is not defined
Таким образом, аргумент функции недоступен вне этой функции. Это произошло, поскольку аргумент функции является локальной переменной. Он существует только во время выполнения функции и доступен только внутри неё. Также говорят, что аргумент функции находится в локальной области видимости функции.
Кроме локальной, существует глобальная область видимости. Переменные, созданные вне функций, то есть в основном коде программе, находятся в глобальной области видимости. Это означает, что к ним можно получить доступ в любой части программы. В следующем примере в функции используется строка password из глобальной области видимости:
def check_password(pwd):
return pwd == password
password = "Python"
print(check_password("123"))
Вывод программы:
False
Возможность изменения значения переменной из глобальной области видимости зависит от того к какому типу данных она относится — к изменяемому или неизменяемому. Например, если переменная является списком, то, применив к нему изменяющие его операции и методы, список изменит своё значение:
def list_modify():
del sample[-1]
sample = [1, 2, 3]
list_modify()
print(sample)
Вывод программы:
[1, 2]
Если же попытаться записать новое значение во внешнюю переменную (не важно — изменяемого или неизменяемого типа), то внутри функции будет создана локальная переменная с тем же именем, что и у внешней:
def list_modify():
sample = [4, 5, 6]
sample = [1, 2, 3]
list_modify()
print(sample)
Вывод программы:
[1, 2, 3]
Мы уже знаем, что аргумент функции — это локальная переменная. К нему также относится правило: изменение значения переменной (если это разрешено типом данных) действует на внешнюю переменную, а присваивание нового значения создаёт локальную переменную функции:
def list_modify_1(list_arg):
# создаём новый локальный список, не имеющий связи с внешним
list_arg = [1, 2, 3, 4]
def list_modify_2(list_arg):
# меняем исходный внешний список, переданный как аргумент
list_arg += [4]
sample_1 = [1, 2, 3]
sample_2 = [1, 2, 3]
list_modify_1(sample_1)
list_modify_2(sample_2)
print(sample_1)
print(sample_2)
Вывод программы:
[1, 2, 3] [1, 2, 3, 4]
Если в функции необходимо менять значения переменных из глобальной области видимости путём операции присваивания, то необходимо в теле функции сделать эти переменные глобальными с помощью ключевого слова global
. Тогда в функции не будут создаваться локальные переменные с такими же именами, а значение поменяется в глобальной переменной:
def inc():
global x
x += 1
print(f"Количество вызовов функции равно {x}.")
x = 0
inc()
inc()
inc()
Вывод программы:
Количество запусков функции равно 1. Количество запусков функции равно 2. Количество запусков функции равно 3.
Однако использование глобальных переменных будет приводить к усложнению анализа программы, так как изменить своё значение глобальная переменная может в практически в любой части программы. Поэтому использовать глобальные переменные можно только в случае, если это действительно необходимо, и написать программу без них сложнее или невозможно. Нашу программу можно написать и без глобальных переменных, для этого достаточно передавать в функцию значение, полученное с предыдущего вызова функции.
def f(count):
count += 1
print(f'Количество вызовов функции равно {count}.')
return count
count_f = 0
count_f = f(count_f)
count_f = f(count_f)
count_f = f(count_f)
Вывод программы:
Количество запусков функции равно 1. Количество запусков функции равно 2. Количество запусков функции равно 3.