- Python передача данных между функциями
- Функция как параметр функции
- Функция как результат функции
- Что вы не знали и передаче параметров в функции
- Передача параметров в других языках
- Использует ли Python модель передачи по значению?
- Использует ли Python передачу по ссылке?
- Объекты в Python
- Изменяемые и неизменяемые объекты
- Переменные и их имя
- В Python используется передача параметров через присваивание
- Как передать результат функции в другую функцию, python?
Python передача данных между функциями
В Python функция фактически представляет отдельный тип. Так мы можем присвоить переменной какую-нибудь функцию и затем, используя переменную, вызывать данную функцию. Например:
def say_hello(): print("Hello") def say_goodbye(): print("Good Bye") message = say_hello message() # Hello message = say_goodbye message() # Good Bye
В данном случае переменной message присваивается одна из функций. Сначала ей передается функция say_hello() :
После этого переменная message будет указывать на данную функцию, то есть фактически представлять функцию say_hello. А это значит, что мы можем вызывать переменную message как обычную функцию:
Фактически это приведет к выполнению функции say_hello, и на консоль будет выведена строка «Hello». Затем подобным образом мы можем передать переменной message другую функцию и вызвать ее.
Подобным образом можно через переменную вызывать функцию с параметрами и возвращать ее результат:
def sum(a, b): return a + b def multiply(a, b): return a * b operation = sum result = operation(5, 6) print(result) # 11 operation = multiply print(operation(5, 6)) # 30
Функция как параметр функции
Поскольку функция в Python может представлять такое же значение как строка или число, соответственно мы можем передать ее в качестве параметра в другую функцию. Например, определим функцию, которая выводит на консоль результат некоторой операции:
def do_operation(a, b, operation): result = operation(a, b) print(f"result = ") def sum(a, b): return a + b def multiply(a, b): return a * b do_operation(5, 4, sum) # result = 9 do_operation(5, 4, multiply) # result = 20
В данном случае функция do_operation имеет три параметра, причем третий параметр, как предполагается, будет представлять функцию, которая принимает два параметра и возвращает некоторый результат. Иными словами третий параметр — operation представляет некоторую операцию, но на момент определения функции do_operation мы точно не знаем, что это будет за операция. Мы только знаем, что она принимает два параметр и возвращает какой-то результат, который потом выводится на консоль.
При вызове функции do_operation мы сможем передать в качестве третьего параметра другую функцию, например, функцию sum:
То есть в данном случае параметр operation фактически будет представлять функцию sum и будет возвращать сумму дву чисел.
Затем аналогичным образов в вызов функции do_operation можно передать третьему параметру другую функцию — multiply, которая выполнит умножение чисел:
do_operation(5, 4, multiply) # result = 20
Таким образом, более гибкие по функциональности функции, которые через параметры принимают другие функции.
Функция как результат функции
Также одна функция в Python может возвращать другую функцию. Например, определим функцию, которая в зависимости от значения параметра возвращает ту или иную операцию:
def sum(a, b): return a + b def subtract(a, b): return a - b def multiply(a, b): return a * b def select_operation(choice): if choice == 1: return sum elif choice == 2: return subtract else: return multiply operation = select_operation(1) # operation = sum print(operation(10, 6)) # 16 operation = select_operation(2) # operation = subtract print(operation(10, 6)) # 4 operation = select_operation(3) # operation = multiply print(operation(10, 6)) # 60
В данном случае функция select_operation в зависимости от значения параметра choice возвращает одну из трех функций — sum, subtract и multiply. Затем мы мы можем получить результат функции select_operation в переменную operation:
operation = select_operation(1)
Так, в данном случае в функцию select_operation передается число 1, соответственно она будет возвращать функцию sum. Поэтому переменная operation фактически будет указывать на функцию sum, которая выполняет сложение двух чисел:
print(operation(10, 6)) # 16 - фактически равно sum(10, 6)
Аналогичным образом можно получить и выполнить другие функции.
Что вы не знали и передаче параметров в функции
В Python при вызове функции используется передача параметров по ссылке или по значению? Сегодня мы попытаемся разобраться. В этой статье вы узнаете: Python не использует модели передачи по ссылке и по значению, а применяет передачу параметров через присваивание; о характеристиках объектов; разницу между изменяемыми(mutable) и неизменяемыми (immutable) объектами.
Передача параметров в других языках
Многие языки программирования предлагают две модели передачи параметров в функции/процедуры:
И то, какую модель использует язык программирования, важно знать, поскольку за эффективность кода отвечает программист лично. А теперь попробуем разобраться, какую модель использует язык Python.
Использует ли Python модель передачи по значению?
При передачи по значению в функцию данные копируются в момент её вызова. Здесь важно понять, что данные (значения) именно копируются, это не те же самые значения. Поэтому в теле функции с ними можно делать всё что угодно, в т.ч. изменять, и это не отразится на исходных данных (тех, которые передали), так как это всего лишь их копии.
В Python не применяется модель передачи по значению, но в некоторых случаях можно видеть нечто похожее. Например, рассмотрим следующий пример:
def foo(x): x = 4 a = 3 foo(a) print(a) # 3
Функция вызывается, но изменения оказанные на переменную a больше не действую после возврата из функции, ведь a всё ещё равна 3. Поэтому может показаться, что используется передача по значению, но это не так. Python не копирует значения параметров при вызове функции. Если мы рассмотрим другую функцию:
def clearly_not_pass_by_value(my_list): my_list[0] = 42 l = [1, 2, 3] clearly_not_pass_by_value(l) print(l) # [42, 2, 3]
— то мы четко видим, что элемент исходного списка l был изменен после вызова функции. Значит ли это, что объект списка использовался один и тот же?
Использует ли Python передачу по ссылке?
При передачи по ссылке в момент вызова функции передаются адреса переменных, причем с адресами работают так, как если бы это была обычная переменная (поэтому не нужно дополнительно проводить разыменование, как это делается в Си). Такая модель подразумевает, что исходные переменные и параметры функции — это одни и те же объекты. Изменяя параметры в теле функции, вы изменяете их и в вызывающем контексте.
Так вот Python не использует и эту модель передачи параметров. Взглянем на следующий код:
def not_pass_by_reference(my_list): my_list = [42, 73, 0] l = [1, 2, 3] not_pass_by_reference(l) print(l) # [1, 2, 3]
Мы предполагаем, что функция должна полностью изменить список, но этого не происходит, он остался прежним. Так какая же модель передачи параметров в функции в используется в Python?
Объекты в Python
В Python всё является объектом. Каждый объект характеризуется следующими характеристиками:
- идентифицирумостью (каждый объект обладает уникальными номером),
- типом (каждый тип обладает своими операциями, которые можно применять),
- содержимое самого объекта.
Эти характеристики можно узнать следующим образом:
>>> id(obj) 2698212637504 >>> type(obj) >>> obj [1, 2, 3]
Эти знания нам пригодятся в дальнейшем.
Изменяемые и неизменяемые объекты
Объекты в Python могут быть изменяемыми (mutable) или неизменяемыми (immutable). Это свойство полностью зависит от типа объекта. Иными словами, не/изменяемость является характеристикой типа, а не конкретных объектов.
Тип является изменяемым, если содержимое объекта может быть изменено без изменений его идентификатора и типа.
Список (list) является изменяемым типом данных. Почему? Потому что списки являются контейнерами: в них можно добавлять данные и из можно удалять данные. Иными словами, их можно спокойно изменять.
Ниже приведен пример того, как содержимое списка меняется, но идентификатор остается тем же самым, что бы мы ни делали.
>>> obj = [] >>> id(obj) 2287844221184 >>> obj.append(0); obj.extend([1, 2, 3]); obj [42, 0, 1, 2, 3] >>> id(obj) 2287844221184 >>> obj.pop(0); obj.pop(0); obj.pop(); obj 42 0 3 [1, 2] >>> id(obj) 2287844221184
С другой стороны, содержимое неизменяемых объектов нельзя изменить. Они существует так, как их инициализировали в первый раз. Строка str является хорошим примером неизменяемого типа.
Вызывая различные методы, призванные как-то модифицировать состояние, объекты с неизменяемым типом что-то возвращают, в отличие от изменяемых. Например, метод списка append ничего не возвращает (он изменяет существующий), а методы строки возвращают новую строку (новый объект):
>>> [].append(0) # Ничего не возвращается >>> "Hello, world!".upper() # Возвращается новая строка 'HELLO, WORLD!"
Другим сигналом неизменяемости объекта является невозможность изменить отдельные его элементы, например, при присваивании через индексы:
>>> obj[0] 'H' >>> obj[0] = "h" Traceback (most recent call last): File "", line 1, in TypeError: 'str' object does not support item assignment
Для справки, в Python встроенные типы:
Переменные и их имя
Ещё необходимо понять, что название переменной — это не то же самое, что и сам объект. Например, имя obj был просто некой меткой, которая была связана с объектом с идентификатором 2287844221184 , типом list и содержимым 1, 2, 3 . Это называется механизмом связывания, о котором мы говорил тут.
Мы вольны связывать и другие метки к этому же самому объекту:
>>> foo = bar = baz = obj >>> id(foo) 2698212637504 >>> id(bar) 2698212637504 >>> id(baz) 2698212637504 >>> id(obj) 2698212637504 # При этом, если изменить объект: >>> obj = 5 >>> id(obj) 94830320197056
Как видим все метки обращаются к одному объекту. В Python даже есть специальный оператор is , который проверяет являются ли два объекты одной сущностью (читай: равны ли их id ).
>>> foo is obj True >>> bar is foo True >>> obj is foo True
Изменяя содержимое через одну переменную, эти изменения можно пронаблюдать через другие, поскольку это один и тот же объект. При этом нужно понимать, объекты, которые имеют тот же тип и содержимое, но не id , не являются одним объектом:
В Python используется передача параметров через присваивание
Теперь мы готовы понять, что за модель передачи параметров используется в Python. При вызове функции каждый параметр связывается с соответствующим объектом, указанным в сигнатуре функции.
Так, если мы передаем неизменяемые параметр (например, int ), то у нас нет возможности хоть как-то его изменить. Каждый раз, когда используется присваивание, то создается новый объект, хоть и имеющий то же самое имя. Взгляните на данный пример:
def foo(bar): bar = 3 return bar a = 5 foo(a)
Вызов функции для неизменяемого типа подразумевает, что используется связывание bar = 5 . Сразу после этого в теле функции осуществляется второе связывание bar = 3 . Но все эти объекты разные. Поэтому при использовании неизменяемых объектов в качестве параметров, их передача осуществляется как будто по схеме передаче значений.
Как передать результат функции в другую функцию, python?
Осваиваю классы, ооп, но пока запутано. В голове путаются тропинки путешествия данных с одного метода в другой, третий и т.д,
Практикую, ставлю разные задачи и пытаюсь выполнить..
вот код — https://jsbin.com/nitocu/edit?js
#coding:utf-8 class MyClass: def __init__(self,x,y,z): self.x=x self.y=y self.z=z def calc_method(self,x,y,z): return (x + y/z) def printing_calc_result(calc_method): print calc_method # - хочу показать результат подсчета а не показать то что это функция) ########################################## root = MyClass(150,60,40) root.printing_calc_result()
доступ к методам тоже можно осуществлять по self. и в методы передавать свойства класса не надо им о свойствах изветсно
class MyClass:
def __init__(self,x,y,z):
self.x=x
self.y=y
self.z=z
def calc_method(self):
return (self.x + self.y/self.z)
def printing_calc_result(self):
print (self.calc_method() )# — хочу показать результат подсчета а не показать то что это функция)
root = MyClass(150,60,40)
root.printing_calc_result()
все стало ясно а именно self.calc_method() — то что нужно в данном случае.
Не просто представить с первого раза как работает self.