Как изменить переменную внутри функции python

Как изменить внешнюю переменную типа int внутри функций? Python Решение и ответ на вопрос 1594202

kquick

6 / 6 / 5

Регистрация: 15.05.2014

Сообщений: 104

1

27.11.2015, 08:49. Показов 6955. Ответов 9

Метки нет (Все метки)


Предположим есть переменная для хранения чисел типа int. Хотелось бы изменять её внутри функций и затем использовать её в основном модуле. Как это можно просто сделать?

Хотелось бы использовать нечто вроде:

Python
1
2
3
4
5
6
def inc(x):
    x += 1 # fail
if __name__ == '__main__':
    a = 1
    inc(a)
    print(a)

Но для примитивного типа это неработает. Можно создать список из одного элемента и с ним работать:

Python
1
2
3
4
5
6
def inc(x):
    x[0] += 1 # ok
if __name__ == '__main__':
    a = [1]
    inc(a)
    print(a[0])

В этом случае теряется читаемость. И вообще, прйдется писать во всех функциях [0].

Можно сделать класс и перегрузить операторы для основных операций:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A(object):
    def __init__(self, data):
        self.data = data
    def __repr__(self):
        return self.data
    def __str__(self):
        return str(self.data)
    def __iadd__(self, other):
        self.data += other
def inc(x):
    x += 1 # ok
if __name__ == '__main__':
    a = A(1)
    inc(a)
    print(a)

Может есть какой-то более лучший подход к решению этой проблемы?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Vigi

623 / 464 / 178

Регистрация: 28.05.2012

Сообщений: 1,386

27.11.2015, 09:10

2

Python
1
2
3
def inc(x):
    global a
    a += 1



1



0x10

3254 / 2056 / 351

Регистрация: 24.11.2012

Сообщений: 4,909

27.11.2015, 10:07

3

Цитата
Сообщение от kquick
Посмотреть сообщение

Может есть какой-то более лучший подход к решению этой проблемы?

Предположим, что функция inc выбрана исключительно для демонстрации.

Python
1
2
3
4
5
6
def inc(a):
    return a + 1
 
 
a = 1
a = inc(a)



1



kquick

6 / 6 / 5

Регистрация: 15.05.2014

Сообщений: 104

27.11.2015, 10:15

 [ТС]

4

Цитата
Сообщение от Vigi
Посмотреть сообщение

Python
1
2
3
def inc(x):
* * global a
* * a += 1

Функции не должны ничего знать про название передаваемой переменной. При изменении оной придется изменять все функции, предположим их 1000.

Цитата
Сообщение от 0x10
Посмотреть сообщение

Python
1
2
3
4
def inc(a):
* * return a + 1
a = 1
a = inc(a)

А если хотим, чтобы функция возвращала что-нибудь другое, но при этом изменяла a? Можно, конечно сделать так:

Python
1
2
3
4
5
6
def inc(a):
    return (a + 1, -a)
if __name__ == '__main__':
    a = 1
    a, something= inc(a)
    print(a, something)

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

Не по теме:

Python
1
2
3
4
5
6
7
def inc(a):
    # меняем a
    return -a
if __name__ == '__main__':
    a = 1
    something = inc(a)
    print(a, something)



0



3254 / 2056 / 351

Регистрация: 24.11.2012

Сообщений: 4,909

27.11.2015, 10:20

5

Цитата
Сообщение от kquick
Посмотреть сообщение

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

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

Каждый out-параметр функции — это сайд-эффект. Множество out-параметров усложняют понимание и отладку кода. Лучше пересмотреть такой дизайн.



1



dondublon

Эксперт Python

4606 / 2027 / 359

Регистрация: 17.03.2012

Сообщений: 10,081

Записей в блоге: 6

27.11.2015, 10:24

6

Глобальные переменные — зло лютое, их нельзя использовать.
Используйте ctypes.

Python
1
2
3
4
5
6
7
from ctypes import c_int
x = c_int(18)
 
def inc(i):
    i.value += 1
 
print x.value

Добавлено через 3 минуты
Или ещё вариант — список из одного значения.

Python
1
2
3
4
5
6
g = [12]
 
def inc(i):
    i[0] += 1
 
inc(g)



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



Эксперт Python

4606 / 2027 / 359

Регистрация: 17.03.2012

Сообщений: 10,081

Записей в блоге: 6

27.11.2015, 10:34

8

Цитата
Сообщение от 0x10
Посмотреть сообщение

оба варианта были в первом посте.

Да, второй был. Просмотрел. Первого не было.

Цитата
Сообщение от 0x10
Посмотреть сообщение

Вариант с ctypes похож на создание своей обертки,

Ну так тут и нужна обёртка, никак не обойдёшь.

Цитата
Сообщение от 0x10
Посмотреть сообщение

Из документации:

Я в курсе.

Цитата
Сообщение от 0x10
Посмотреть сообщение

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

Это стандартная библиотека.



1



3254 / 2056 / 351

Регистрация: 24.11.2012

Сообщений: 4,909

27.11.2015, 10:38

9

Цитата
Сообщение от dondublon
Посмотреть сообщение

Это стандартная библиотека.

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



1



dondublon

Эксперт Python

4606 / 2027 / 359

Регистрация: 17.03.2012

Сообщений: 10,081

Записей в блоге: 6

27.11.2015, 11:16

10

Ещё вариант.
Зачем нам функция? Чтобы многократно вызывать один и тот же код. Этот код можно записать в строку и его многократно вызывать:

Python
1
2
g = 12
exec('g+=1')

Добавлено через 12 минут
К предыдущему. Для быстродействия код надо скомпилировать:

Python
1
2
3
import codeop
cc = codeop.compile_command('g+=1')
exec(cc)



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.

Понравилась статья? Поделить с друзьями:

Читайте также:

  • Как изменить переменную php через js
  • Как изменить пароль электронной почты на телефоне айфон
  • Как изменить переменную path linux
  • Как изменить пароль электронной почты на телефоне mail ru
  • Как изменить переменную css через js

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии