- •§0.1. Базовые знания
- •§0.2. Где достать интерпретатор языка Питон?
- •§0.3. Установка интерпретатора языка Питон в unix
- •§0.3.1. Установка/обновление Питона из грт-пакета
- •§0.3.2. Установка Питона из исходного кода
- •§0.4. Установка Питона в ос Windows
- •§0.5. Запуск программ, написанных на Питоне
- •§0.6. Среда разработки
- •§1.1. Алгоритмы и программы
- •§1.2. Языки программирования и уровни абстракции
- •Глава 1. Базовые понятия
- •§1.3. Формальные и естественные языки
- •§1.4. Интерпретаторы и компиляторы
- •§1.5. Первая программа
- •§1.6. Что такое отладка?
- •§1.6.1. Синтаксические ошибки (syntax errors)
- •§1.6.2. Ошибки выполнения (runtime errors)
- •§1.6.3. Семантические ошибки (semantic errors)
- •§1.6.4. Процесс отладки
- •Глава 2. Переменные, операции и выражения
- •§2.1. Значения и типы
- •§2.2. Преобразование типов
- •§2.3. Переменные
- •§2.4. Имена переменных и ключевые слова
- •§2.5. Выражения
- •§2.6. Выполнение выражений
- •§2.7. Операторы и операнды
- •§2.8. Порядок операций
- •§2.9. Простейшие операции над строками
- •§2.10. Композиция
- •Глава 3. Функции §3.1. Подпрограммы
- •§3.2. Вызовы функций
- •§3.3. Справочная система
- •§3.4. Импорт модулей и математические функции
- •§3.5. Композиция
- •§3.6. Создание функций
- •§3.7. Параметры и аргументы
- •§3.8. Локальные переменные
- •§3.9. Поток выполнения
- •§3.10. Стековые диаграммы
- •§3.11. Функции, возвращающие результат
- •Глава 4. Компьютерная графика
- •Глава 5. Логические выражения, условия и рекурсия §5.1. Комментарии в программах
- •§5.2. Простые логические выражения и логический тип данных
- •§5.3. Логические операторы
- •§5.4. Выполнение по условию и «пустота»
- •§5.5. Ввод данных с клавиатуры
- •§5.6. Альтернативные ветки программы (Chained conditionals)
- •§5.7. Пустые блоки
- •§5.8. Вложенные условные операторы (Nested conditionals)
- •§5.9. Рекурсия
- •§5.10. Стековые диаграммы рекурсивных вызовов
- •§5.11. Максимальная глубина рекурсии
- •§5.12. Числа Фибоначчи
- •Глава 6. Циклы
- •§6.1. Оператор цикла while
- •§6.2. Счетчики
- •§6.3. Бесконечные циклы
- •§6.4. Альтернативная ветка цикла while
- •§6.5. Табулирование функций
- •§6.6. Специальные и экранируемые символы
- •§6.7. Числа Фибоначчи и оператор цикла while
- •§6.8. Вложенные операторы цикла и двумерные таблицы
- •§6.9. Классификация операторов цикла
- •§6.10. Управляющие структуры
- •Глава 7. Строки
- •§7.1. Оператор индексирования
- •§7.2. Длина строки и отрицательные индексы
- •§7.3. Перебор и цикл for
- •§7.4. Срезы строк
- •§7.5. Сравнение строк
- •§7.6. Строки нельзя изменить
- •§7.7. Функция find
- •§7.8. Циклы и счётчики
- •§7.9. Модуль string
- •§7.10. Классификация символов
- •§10.2. Операции над словарями
- •§10.3. Методы словарей
- •§10.4. Использование псевдонимов и копирование
- •§10.5. Разряженные матрицы
- •§10.6. Подсказки
- •§10.7. Тип «длинное целое число»
- •§10.8. Подсчет букв
§3.7. Параметры и аргументы
Итак, мы научились создавать собственные функции и различать определения и вызовы функций. Теперь определимся с терминологией: чем отличается параметр функции от ее аргумента? Разница есть и большая, но вы могли ее не уловить.
Параметрами функции называют список переменных, которым присваиваются передаваемые при вызове этой функции значения. А сами передаваемые значения называют аргументами. В своем теле функция оперирует параметрами, но не аргументами. Разберем пример из предыдущего раздела:
>» |
def printAnything(obj print object |
ect) : |
|
>» |
printAnything("Some s |
tring") |
|
Some string |
|
||
>» |
number = 15 |
|
|
>» |
printAnything(number) |
|
|
15 |
|
|
|
Здесь переменная object является параметром, а строка "Some string" и переменная number - аргументами. Таким образом, правильно будет сказать «передать аргумент» или «передать значение в качестве параметра», но не «передать функции параметр». Старайтесь не путать эти понятия.
§3.8. Локальные переменные
Вернемся к функции поиска корней квадратного уравнения PrintRoots (). Она выглядит приблизительно так:
def printRoots(a, b, с):
40
Ревизия: 170
Функции
D = b**2 - |
4 * a |
* |
С |
|
|
|
|
|||
import |
math |
|
|
|
|
|
|
|||
xl = (- |
-b + |
math. |
sqrt(D)) |
/ |
2 |
* |
a |
|||
x2 = (- |
-b - |
math. |
sqrt(D)) |
/ |
2 |
* |
a |
|||
'xl = |
= ', xl |
r |
'\nx2 = |
_ ? / |
x2 |
|
||||
Последовательность символов \п в последней строке тела функции дает указание команде print перейти на новую строку. В теле функции определено три переменные: D, xl и х2. Такие переменные называют локальными, т.к. к ним можно обратиться только в самом теле функции. После завершения работы функции они стираются из памяти. Это может проиллюстрировать следующая программа:
def printRoots |
(a, b, |
c) : |
|
|
|
|
|
D = b**2 - |
4 * a |
* с |
|
|
|
|
|
import |
math |
|
|
|
|
|
|
xl = ( |
-b + |
math. |
sqrt(D)) |
/ |
2 |
* |
a |
x2 = ( |
-b - |
math. |
sqrt(D)) |
/ |
2 |
* |
a |
'xl = |
= ', xl |
, '\nx2 = |
_ ? / |
x2 |
|
||
printRoots |
(1.0, |
o, - |
1.0) |
|
|
|
|
print D |
|
|
|
|
|
|
|
Если запустить ее, то интерпретатор сразу после завершения работы функции
PrintRoots () выведет ошибку вида:
$ python p |
rog5.py |
|
|
|
|
xl = 1.0 |
|
|
|
|
|
х2 = -1.0 |
|
|
|
|
|
Traceback |
(most recent |
call |
las |
t) : |
|
File "prog5.py", |
line |
12, |
in |
9 |
|
D |
|
|
|
|
|
NameError: |
name 'D |
is |
not |
defined |
|
Почему было выбрано такое поведение? Как вы думаете? Модифицируем нашу программу таким образом:
def printRoots(a, b, с): |
|
D = b**2 - 4 * а * с |
|
import math |
|
print "In function D = ", D |
|
xl = (-b + math.sqrt(D)) / 2 * |
a |
x2 = (-b - math.sqrt(D)) / 2 * |
a |
print "xl =", xl, "\nx2 =", x2 |
|
41
Ревизия: 170
Функции
D = 'test'
print "Before function call D = ", D
printRoots(1.0, 0, -1.0)
print "After function call D = ", D
Запустим программу и проанализируем результат.
$ python prog5. |
РУ |
|
|
Before function call D |
= test |
||
In function D = |
= 4 |
0 |
|
xl = 1.0 |
|
|
|
x2 = -1.0 |
|
|
|
After function |
call D = |
test |
|
Итак, после определения функции printRoots () мы присвоили переменной D значение "test" и проверили результат: вывелась строка "test". Затем вызвали функцию printRoots (), в теле которой после присвоения переменной D результата вычисления формулы дискриминанта так же выводится значение переменной D: 4.0. После завершения работы функции мы снова выводим значение переменной D: на этот раз присвоенное значение снова равно строке "test".
На самом деле, D в основной программе и D в теле функции printRoots () - это две разные переменные. Проверить это можно, немного модифицировав нашу программу. Воспользуемся функцией id(). Она возвращает адрес объекта в памяти. Измененная программа будет выглядеть приблизительно так:
def printRoots(a, b, с): D = b**2 - 4 * а * с import math
print "In function D = ", D, "\nAdress:", id(D), "\n" xl = (-b + math.sqrt(D)) / 2 * a x2 = (-b - math.sqrt(D)) / 2 * a print "xl =", xl, "\nx2 =", x2
D = "test"
print "Before function call D = ", D, "\nAdress:", id(D), "\n"
printRoots(1.0, 0, -1.0)
print "After function call D = ", D, "\nAdress:", id(D), "\n"
Результат работы программы будет следующим:
$ python prog5.py |
|
Before function call D = |
= test |
Adress: 135287104 |
|
42
Ревизия: 170
Функции
In function D = 4.0 |
|
Adress: 135293780 |
|
xl = 1.0 |
|
x2 = -1.0 |
|
After function call D = |
= test |
Adress: 135287104 |
|
На вашем компьютере адреса могут быть другими, но выводы вы сможете сделать такие же: адреса D в основной программе и D в теле функции printRoots () различаются. Что и требовалось доказать.
Упражнение. Являются ли параметры функции локальными переменными?
