Глючный код на Python: 10 самых распространенных ошибок, которые допускают разработчики
Python — это интерпретируемый, объектно-ориентированный язык программирования высокого уровня с динамической семантикой. Встроенные структуры данных высокого уровня в сочетании с динамической типизацией и динамическим связыванием делают его очень привлекательным для БРПС (быстрой разработки прикладных средств), а также для использования в качестве скриптового и связующего языка для подключения существующих компонентов или сервисов. Python поддерживает модули и пакеты, тем самым поощряя модульность программы и повторное использование кода.
О данной статье
Простота и легкость в освоении данного языка может ввести разработчиков в заблуждение (особенно тех, кто еще только начинает изучать Python), так что можно упустить из виду некоторые важные тонкости и недооценить силу разнообразия возможных решений с помощью Python.
Имея это в виду, в этой статье представлен «топ-10» тонких, трудных для обнаружения ошибок, которые могут допустить даже продвинутые разработчики Python.
Ошибка № 1: неправильное использование выражений в качестве значений по умолчанию для аргументов функций
Python позволяет указывать, что у функции могут быть необязательные аргументы, путем задания для них значения по умолчанию. Это, конечно, очень удобная особенность языка, но может привести к неприятным последствиям, если тип такого значения будет изменяемым. Например, рассмотрим следующее определение функции:
>>> def foo(bar=[]): # bar - это необязательный аргумент # и по умолчанию равен пустому списку. . bar.append("baz") # эта строка может стать проблемой. . return bar
Распространенная ошибка в данном случае — это думать, что значение необязательного аргумента будет устанавливаться в значение по умолчанию каждый раз, как функция будет вызываться без значения для этого аргумента. В приведенном выше коде, например, можно предположить, что повторно вызывая функцию foo() (то есть без указания значения для агрумента bar), она всегда будет возвращать «baz», поскольку предполагается, что каждый раз, когда вызывается foo () (без указания аргумента bar), bar устанавливается в [ ] (т. е. новый пустой список).
Но давайте посмотрим что же будет происходить на самом деле:
>>> foo() ["baz"] >>> foo() ["baz", "baz"] >>> foo() ["baz", "baz", "baz"]
А? Почему функция продолжает добавлять значение по умолчанию «baz» к существующему списку каждый раз, когда вызывается foo(), вместо того, чтобы каждый раз создавать новый список?
Ответом на данный вопрос будет более глубокое понимание того, что творится у Python «под капотом». А именно: значение по умолчанию для функции инициализируется только один раз, во время определения функции. Таким образом, аргумент bar инициализируется по умолчанию (т. е. пустым списком) только тогда, когда foo() определен впервые, но последующие вызовы foo() (т. е. без указания аргумента bar) продолжат использовать тот же список, который был создан для аргумента bar в момент первого определения функции.
Для справки, распространенным «обходным путем» для этой ошибки является следующее определение:
>>> def foo(bar=None): . if bar is None: # or if not bar: . bar = [] . bar.append("baz") . return bar . >>> foo() ["baz"] >>> foo() ["baz"] >>> foo() ["baz"]
Ошибка № 2: неправильное использование переменных класса
Рассмотрим следующий пример:
>>> class A(object): . x = 1 . >>> class B(A): . pass . >>> class C(A): . pass . >>> print A.x, B.x, C.x 1 1 1
Вроде все в порядке.
>>> B.x = 2 >>> print A.x, B.x, C.x 1 2 1
Ага, все как и ожидалось.
>>> A.x = 3 >>> print A.x, B.x, C.x 3 2 3
Что за черт?! Мы же только изменили A.x. Почему же C.x тоже изменилось?
В Python переменные класса обрабатываются как словари и следуют тому, что часто называют Порядком разрешения методов (MRO). Таким образом, в приведенном выше коде, поскольку атрибут x не найден в классе C, он будет найден в его базовых классах (только A в приведенном выше примере, хотя Python поддерживает множественное наследование). Другими словами, C не имеет своего собственного свойства x, независимого от A. Таким образом, ссылки на C.x фактически являются ссылками на A.x. Это будет вызывать проблемы, если не обрабатывать такие случаи должным образом. Так что при изучении Python обратите особое внимание на аттрибуты класса и работу с ними.
Ошибка № 3: неправильное указание параметров для блока исключения
Предположим, что у вас есть следующий кусок кода:
>>> try: . l = ["a", "b"] . int(l[2]) . except ValueError, IndexError: # To catch both exceptions, right? . pass . Traceback (most recent call last): File "", line 3, in IndexError: list index out of range
Проблема здесь заключается в том, что выражение except не принимает список исключений, указанных таким образом. Скорее, в Python 2.x выражение «except Exception, e» используется для привязки исключения к необязательному второму заданному второму параметру (в данном случае e), чтобы сделать его доступным для дальнейшей проверки. В результате в приведенном выше коде исключение IndexError не перехватывается выражением except; скорее, вместо этого исключение заканчивается привязкой к параметру с именем IndexError.
Правильный способ перехвата нескольких исключений с помощью выражения except — указать первый параметр в виде кортежа, содержащего все исключения, которые нужно перехватить. Кроме того, для максимальной совместимости используйте ключевое слово as, так как этот синтаксис поддерживается как в Python 2, так и в Python 3:
>>> try: . l = ["a", "b"] . int(l[2]) . except (ValueError, IndexError) as e: . pass . >>>
Ошибка № 4: непонимание правил области видимости Python
Область видимости в Python основана на так называемом правиле LEGB, которое является аббревиатурой Local (имена, назначенные любым способом внутри функции (def или lambda), и не объявленные глобальными в этой функции), Enclosing (имя в локальной области действия любых статически включающих функций (def или lambda), от внутреннего к внешнему), Global (имена, назначенные на верхнем уровне файла модуля, или путем выполнения global инструкции в def внутри файла), Built-in (имена, предварительно назначенные в модуле встроенных имен: open, range, SyntaxError . ). Кажется достаточно просто, верно? Ну, на самом деле, есть некоторые тонкости в том, как это работает в Python, что подводит нас к общей более сложной проблеме программирования на Python ниже. Рассмотрим следующей пример:
>>> x = 10 >>> def foo(): . x += 1 . print x . >>> foo() Traceback (most recent call last): File "", line 1, in File "", line 2, in foo UnboundLocalError: local variable 'x' referenced before assignment
Вышеуказанная ошибка возникает потому, что, когда вы присваиваете переменную в области видимости, Python автоматически считает ее локальной для этой области и скрывает любую переменную с аналогичным именем в любой вышестоящей области.
Таким образом, многие удивляются, когда получают UnboundLocalError в ранее работающем коде, когда он модифицируется путем добавления оператора присваивания где-нибудь в теле функции.
Эта особенность особенно сбивает разработчиков с толку при использовании списков. Рассмотрим следующий пример:
>>> lst = [1, 2, 3] >>> def foo1(): . lst.append(5) # Это работает нормально. . >>> foo1() >>> lst [1, 2, 3, 5] >>> lst = [1, 2, 3] >>> def foo2(): . lst += [5] # . а вот это падает! . >>> foo2() Traceback (most recent call last): File "", line 1, in File "", line 2, in foo UnboundLocalError: local variable 'lst' referenced before assignment
А? Почему foo2 падает, в то время как foo1 работает нормально?
Ответ такой же, как в предыдущем примере, но, по распространенному мнению, здесь ситуация более тонкая. foo1 не применяет оператор присваивания к lst, тогда как foo2 — да. Помня, что lst + = [5] на самом деле является просто сокращением для lst = lst + [5], мы видим, что мы пытаемся присвоить значение lst (поэтому Python предполагает, что он находится в локальной области видимости). Однако значение, которое мы хотим присвоить lst, основано на самом lst (опять же, теперь предполагается, что он находится в локальной области видимости), который еще не был определен. И мы получаем ошибку.
Ошибка № 5: изменение списка во время итерации по нему
Проблема в следующем куске кода должна быть достаточно очевидной:
>>> odd = lambda x : bool(x % 2) >>> numbers = [n for n in range(10)] >>> for i in range(len(numbers)): . if odd(numbers[i]): . del numbers[i] # BAD: Deleting item from a list while iterating over it . Traceback (most recent call last): File "", line 2, in IndexError: list index out of range
Удаление элемента из списка или массива во время итерации по нему — это проблема Python, которая хорошо известна любому опытному разработчику программного обеспечения. Но, хотя приведенный выше пример может быть достаточно очевидным, даже опытные разработчики могут встать на эти грабли в гораздо более сложном коде.
К счастью, Python включает в себя ряд элегантных парадигм программирования, которые при правильном использовании могут привести к значительному упрощению и оптимизации кода. Дополнительным приятным следствием этого является то, что в более простом коде вероятность попасться на ошибку случайного удаления элемента списка во время итерации по нему значительно меньше. Одна из таких парадигм — генераторы списков. Кроме того, понимание работы генераторов списков особенно полезны для избежания этой конкретной проблемы, как показано в этой альтернативной реализацией приведенного выше кода, которая прекрасно работает:
>>> odd = lambda x : bool(x % 2) >>> numbers = [n for n in range(10)] >>> numbers[:] = [n for n in numbers if not odd(n)] # ahh, the beauty of it all >>> numbers [0, 2, 4, 6, 8]
Ошибка № 6: непонимание того, как Python связывает переменные в замыканиях
Рассмотрим следующий пример:
>>> def create_multipliers(): . return [lambda x : i * x for i in range(5)] >>> for multiplier in create_multipliers(): . print multiplier(2) .
Вы можете ожидать следующий вывод:
0 2 4 6 8
Но на самом деле вы получите вот что:
8 8 8 8 8
Это происходит из-за поздней привязки в Python, которое заключается в том, что значения переменных, используемых в замыканиях, ищутся во время вызова внутренней функции. Таким образом, в приведенном выше коде всякий раз, когда вызывается какая-либо из возвращаемых функций, значение i ищется в окружающей области видимости во время ее вызова (а к тому времени цикл уже завершился, поэтому i уже был присвоен конечный результат — значение 4).
Решение этой распространенной проблемы с Python будет таким:
>>> def create_multipliers(): . return [lambda x, i=i : i * x for i in range(5)] . >>> for multiplier in create_multipliers(): . print multiplier(2) . 0 2 4 6 8
Вуаля! Мы используем здесь аргументы по умолчанию для генерации анонимных функций для достижения желаемого поведения. Некоторые назвали бы это решение элегантным. Некоторые —
тонким. Некоторые ненавидят подобные штуки. Но если вы разработчик Python, в любом случае, это важно понимать.
Ошибка № 7: создание циклических зависимостей модуля
Допустим, у вас есть два файла, a.py и b.py, каждый из которых импортирует другой, следующим образом:
import b def f(): return b.x print f()
import a x = 1 def g(): print a.f()
Сначала попробуем импортировать a.py:
>>> import a 1
Сработало просто отлично. Возможно, это вас удивляет. В конце концов, модули циклически импортируют друг друга и это, вероятно, должено быть проблемой, не так ли?
Ответ заключается в том, что простое наличие циклического импорта модулей само по себе не является проблемой в Python. Если модуль уже был импортирован, Python достаточно умен, чтобы не пытаться повторно импортировать его. Однако, в зависимости от точки, в которой каждый модуль пытается получить доступ к функциям или переменным, определенным в другом, вы действительно можете столкнуться с проблемами.
Итак, возвращаясь к нашему примеру, когда мы импортировали a.py, у него не было проблем с импортом b.py, поскольку b.py не требует, чтобы что-либо из a.py было определено во время его импорта. Единственная ссылка в b.py на a — это вызов a.f(). Но этот вызов в g() и ничего в a.py или b.py не вызывает g(). Так что все работает прекрасно.
Но что произойдет, если мы попытаемся импортировать b.py (без предварительного импорта a.py, то есть):
>>> import b Traceback (most recent call last): File "", line 1, in File "b.py", line 1, in import a File "a.py", line 6, in print f() File "a.py", line 4, in f return b.x AttributeError: 'module' object has no attribute 'x'
Ой-ой. Это не хорошо! Проблема здесь в том, что в процессе импорта b.py он пытается импортировать a.py, который, в свою очередь, вызывает f(), который пытается получить доступ к b.x. Но b.x еще не было определено. Отсюда исключение AttributeError.
По крайней мере, одно из решений этой проблемы довольно тривиально. Просто измените b.py, чтобы импортировать a.py в g():
x = 1 def g(): import a # This will be evaluated only when g() is called print a.f()
Теперь, когда мы его импортируем, все нормально:
>>> import b >>> b.g() 1 # Printed a first time since module 'a' calls 'print f()' at the end 1 # Printed a second time, this one is our call to 'g'
Ошибка № 8: пересечение имен с именами модулями стандартной библиотеки Python
Одна из прелестей Python — это множество модулей, которые поставляются «из коробки». Но в результате, если вы сознательно не будете за этим следить, можно столкнуться с тем, что имя вашего модуля может быть с тем же именем, что и модуль в стандартной библиотеке, поставляемой с Python (например, в вашем коде может быть модуль с именем email.py, который будет конфликтовать со модулем стандартной библиотеки с таким же именем).
Это может привести к серьезным проблемам. Например, если какой-нибудь из модулей будет пытаться импортировать версию модуля из стандартной библиотеки Python, а у вас в проекте будет модуль с таким же именем, который и будет по ошибке импортирован вместо модуля из стандартной библиотеки.
Поэтому следует проявлять осторожность, чтобы не использовать те же имена, что и в модулях стандартной библиотеки Python. Гораздо проще изменить название модуля в своем проекте, нежели подать запрос на изменение имени модуля в стандартной библиотеке и получить на него одобрение.
Ошибка № 9: неспособность учесть различия Python 2 и Python 3
Рассмотрим следующий файл foo.py:
import sys def bar(i): if i == 1: raise KeyError(1) if i == 2: raise ValueError(2) def bad(): e = None try: bar(int(sys.argv[1])) except KeyError as e: print('key error') except ValueError as e: print('value error') print(e) bad()
На Python 2 он отработает нормально:
$ python foo.py 1 key error 1 $ python foo.py 2 value error 2
Но теперь давайте посмотрим как он будет работать в Python 3:
$ python3 foo.py 1 key error Traceback (most recent call last): File "foo.py", line 19, in bad() File "foo.py", line 17, in bad print(e) UnboundLocalError: local variable 'e' referenced before assignment
Что здесь только что произошло? «Проблема» в том, что в Python 3 объект в блоке исключения недоступен за его пределами. (Причина этого заключается в том, что в противном случае объекты в этом блоке будут сохраняться в памяти до тех пор, пока сборщик мусора не запустится и не удалит ссылки на них оттуда).
Один из способов избежать этой проблемы — сохранить ссылку на объект блока исключения за пределами этого блока, чтобы он оставался доступным. Вот версия предыдущего примера, которая использует эту технику, тем самым получая код, который подходит как для Python 2, так и для Python 3:
import sys def bar(i): if i == 1: raise KeyError(1) if i == 2: raise ValueError(2) def good(): exception = None try: bar(int(sys.argv[1])) except KeyError as e: exception = e print('key error') except ValueError as e: exception = e print('value error') print(exception) good()
Запустим его в Python 3:
$ python3 foo.py 1 key error 1 $ python3 foo.py 2 value error 2
Ошибка № 10: неправильное использование метода __del__
Допустим, у вас есть вот такой файл mod.py:
import foo class Bar(object): . def __del__(self): foo.cleanup(self.myhandle)
И вы пытаетесь сделать вот такое из другого another_mod.py:
import mod mybar = mod.Bar()
И получите ужасный AttributeError.
Почему? Потому что, как сообщается здесь, когда интерпретатор отключается, глобальные переменные модуля все имеют значение None. В результате в приведенном выше примере, в момент вызова __del__, имя foo уже было установлено в None.
Решением этой «задачи со звездочкой» будет использование atexit.register(). Таким образом, когда ваша программа завершает выполнение (то есть при нормальном выходе из нее), ваши handle’ы удаляются до того, как интерпретатор звершает работу.
С учетом этого, исправление для приведенного выше кода mod.py может выглядеть примерно так:
import foo import atexit def cleanup(handle): foo.cleanup(handle) class Bar(object): def __init__(self): . atexit.register(cleanup, self.myhandle)
Подобная реализация обеспечивает простой и надежный способ вызова любой необходимой очистки после обычного завершения программы. Очевидно, что решение о том, как поступить с объектом, который связан с имненем self.myhandle, остается за foo.cleanup, но, думаю, идею вы поняли.
Заключение
Python — это мощный и гибкий язык со множеством механизмов и парадигм, которые могут значительно повысить производительность. Однако, как и в случае с любым программным инструментом или языком, при ограниченном понимании или оценке его возможностей, при разработке могут возникать непредвиденные проблемы.
Ознакомление с нюансами Python, затронутыми в этой статье, поможет оптимизировать использование языка, избегая при этом некоторых распространенных ошибок.
Найдите ошибки в следующем фрагменте кода: var firstName = prompt(«Введите имя»; «сюда»);
var lastName = promt(«Введите фамилию»);
int age = prompt(«Введите возраст»);
alert(Age);
язык js
По сути текст «Сюда» не нужен, а если нужен, то указывается через запятую.
2. Вторая строка пропущена буква «p». prompt
3. var вместо int. В js нет строгой типизации.
4. alert(age) — c маленькой буквы, т.к переменные Age и age — разные.
Объяснение:
Новые вопросы в Информатика
Напиши наименьшее целое число x, для которого истинны оба высказывания: X < 9 X > 6
Кто разработал архитектуру персонального компьютера?
а = input(«Введи час: «) print(«В хвилині — «,(а*60),» секунд») print(«В годині — «,(а*3600),» секунд») print(«В добі — «,(а*(3600*24)),» секунд») pri … nt(«В місяці — «,(а*(3600*24)*30),»або»,»(а*(3600*24)*31)»,» секунд») print(«В році — «,(а*(3600*24)*365),» секунд») что здесь не так
как выйти из сюжетного режима в gta v
решите без генератора чисел и def если можно Задание 1Создайте программу «Фирма». Нужно хранить информацию о человеке: ФИО, телефон, рабочий email,наз … вание должности, номер кабинета, skype. Требуетсяреализовать возможность добавления, удаления, поиска, замены данных. Используйте словарь для храненияинформации.Задание 2Создайте программу «Книжная коллекция». Нужнохранить информацию о книгах: автор, название книги,жанр, год выпуска, количество страниц, издательство.Требуется реализовать возможность добавления, удаления, поиска, замены данных. Используйте словарь дляхранения информации.
Тест-контрольная работа «Начала программирование»
Внимание! Все тесты в этом разделе разработаны пользователями сайта для собственного использования. Администрация сайта не проверяет возможные ошибки, которые могут встретиться в тестах.
Контрольная работа по теме «Начала программирования» для 8-х классов
Система оценки: 5 балльная
Список вопросов теста
Вопрос 1
Чувствителен ли Python к регистру (большая или маленькая буквы):
Варианты ответов
Вопрос 2
Какие существуют типы переменных в Python (выбрать несколько выриантов):
Варианты ответов
Вопрос 3
Переменная int:
Варианты ответов
- вещественная переменная
- символьная строка
- логическая переменная
- целая переменная
Вопрос 4
Переменная str:
Варианты ответов
- вещественная переменная
- символьная строка
- логическая переменная
- целая переменная
Вопрос 5
Переменная float:
Варианты ответов
- вещественная переменная
- символьная строка
- логическая переменная
- целая переменная
Вопрос 6
Переменная bool:
Варианты ответов
- вещественная переменная
- символьная строка
- логическая переменная
- целая переменная
Вопрос 7
Каков будет результат выполнения int(«88»):
Варианты ответов
Вопрос 8
Каков будет результат выполнения float(«88»):
Варианты ответов
Вопрос 9
Каков будет результат выполнения str(88.0):
Варианты ответов
Вопрос 10
Имена переменных могут включать (выбрать несколько):
Варианты ответов
- Русские буквы
- Латинские буквы
- Пробелы
- Скобки, знаки + = ! ? и др.
- Знак подчёркивания (_)
- Цифры
Вопрос 11
Какие имена являются правильными в Python (выбрать несколько):
Варианты ответов
Вопрос 12
Что будет выведено в результате выполнения программы:
a = 20
b = a + 5
a = b * 100
print(a)
Варианты ответов
Вопрос 13
Что будет выведено в результате следующего действия print(2**20)
Варианты ответов
Вопрос 14
Что будет в результате выполнения следующего действия print(23 % 2)
Варианты ответов
Вопрос 15
Что будет в результате выполнения следующего действия print(23 % 3):
Варианты ответов
Вопрос 16
Результатом выполнения команды print(24 // 3) будет число:
Варианты ответов
Вопрос 17
Что будет результатом выполнения алгоритма:
a = int(input())
b = int(input())
s = a + b
print(s)
Варианты ответов
Вопрос 18
Что будет результатом выполнения алгоритма:
a = input()
b = input()
s = a + b
print(s)
Варианты ответов
Вопрос 19
Что будет в результате выполнения следующего алгоритма:
x = int(input())
if x > 0:
print(x)
else:
print(-x)
Варианты ответов
Вопрос 20
Что будет в результате выполнения программы:
a = int(input())
b = int(input())
if a < b:
print(a)
else:
print(b)
если a = 10, b = 20?
Варианты ответов
Вопрос 21
Какой ряд чисел образуется после выполнения следующего алгоритма:
for i in range(1,10):
print(i)
Варианты ответов
- 1 2 3 4 5 6 7 8 9 10
- 1 2 3 4 5 6 7 8 9
- 0 1 2 3 4 5 6 7 8
Вопрос 22
Какой ряд чисел образуется после выполнения алгоритма:
for i in range(1, 10+1):
print(i)
Варианты ответов
- 1 2 3 4 5 6 7 8 9 10
- 1 2 3 4 5 6 7 8 9 10 11
- 1 4 9 16
Вопрос 23
Что выведет программа после выполнения данного алгоритма:
Входные данные: Иванов
print(‘Как Ваша фамилия?’)
name = input()
print(‘Здравствуйте, ‘+ name + ‘!’ )
Варианты ответов
- Как Ваша фамилия? Здравствуйте, Иванов!
- Как Ваша фамилия? Здравствуйте, Иванов !
- Как Ваша фамилия? Здравствуйте, Иванов !
Вопрос 24
Как обозначается логический оператор И, ИЛИ, НЕ в Python:
Варианты ответов
- or, not, if
- and, or, not
- and, or, if
- and, else, not
Вопрос 25
Что будет в результате выполнения следующего алгоритма программы:
a = int(input())
b = int(input())
if a % 10 == 0 or b % 10 == 0:
print(‘YES’)
else:
print(‘NO’)
если а = 15, b = 45?
Варианты ответов
Вопрос 26
Как будет записано число 18 после выполнения следующего алгоритма:
x = float(input())
print(x)
Варианты ответов
Вопрос 27
Что будет после выполнения следующей программы:
for i in range(4):
print(i)
print(i**2)
Варианты ответов
- 0 0 1 1 3 3 4 4
- 0 0 1 1 2 4 3 4
- 0 0 1 1 2 4 3 9
Вопрос 28
Результатом выполнения алгоритма цикла while будет:
i = 1
while i print(i**2)
i = i + 1
Варианты ответов
- 1 2 4 8 12 14
- 1 2 16 24 32
- 1 4 9 16 25 36 49 64 81 100
Вопрос 29
Определите, что будет напечатано в результате работы следующей программы
s = 0
for i in range(8, 13):
s = s + 12
print(s)
Вопрос 30
Определите значение переменной а после выполнения алгоритма:
a = int(input())
b = int(input())
b = a / 2 * b
a = 2 * a + 3 * b
print(a)
Вопрос 31
Для вычисления квадратного корня из х используется функция:
Варианты ответов
- abs(x)
- sqrt(x)
- math.sqrt(x)
- sqr(x)
Вопрос 32
Для генерации случайного целого числа из интервала [10, 20] необходимо использовать выражение:
Варианты ответов
- random.randint(10, 20)
- random.randint(0, 10) * 2
- random.random(10, 20)
- random.random(0, 10) * 2
Вопрос 33
Определите значение переменной с после выполнения следующего фрагмента:
a = 100
b = 30
a -= b * 3
if a > b:
c = a — b
else:
c = b — a
Варианты ответов
Вопрос 34
if a % 2 == 0:
print(‘Да’)
else:
print(‘Нет’)
позволяет определить, является ли число а:
Варианты ответов
- целым
- двузначным
- чётным
- простым
Вопрос 35
Какие операторы цикла существуют в языке Python?
Варианты ответов
- for
- while
- repeat . until
- loop
Вопрос 36
Цикл в фрагменте программы
p = 2
while p > 0.1:
p *= 0.1
будет исполнен раз
Варианты ответов
- 0
- 1
- 2
- бесконечное число раз
Вопрос 37
Цикл в фрагменте программы:
a = b = 1
while a + b < 8:
a += 1
b += 2
Варианты ответов
Вопрос 38
Определите значения переменных s и i после выполнения фрагмента программы:
s = 0
i = 5
while i >= 0:
s += i
i -= 1
Варианты ответов
- s = 0, i = -1
- s = 5, i = 0
- s = 15, i = 5
- s = 15, i = -1
Вопрос 39
Выберите фрагмент программы, в котором ищется произведение 1 * 2 * 3 * 4 * 5:
Варианты ответов
- p = 0
i = 1
while i i += 1
p *= i - p = 1
i = 1
while i < 6:
i += 1
p *= i - p = 1
i = 1
while i < 6:
p *= i
i += 1 - p = 1
i = 1
while i > 5:
p *= i
i += 1
Вопрос 40
В данном фрагменте программы:
s = 0
for i in range(1, 11):
s += 2 * i
Варианты ответов
- сумма целых чисел от 1 до 10
- сумма чётных чисел от 1 до 10
- удвоенная сумма чисел от 1 до 10
- сумма первых десяти чётных чисел
Получите комплекты видеоуроков + онлайн версии
Сохранить у себя:
Нравится 0
Комментарии 2
Чтобы добавить комментарий зарегистрируйтесь или войдите на сайт
Ирина videouroki.net, 14.09.2022 10:01
Пользователь,
Подскажите где ответы брать?!
Здравствуйте. Благодарим Вас за внимание к нашему сайту. Ответы на тест от пользователя сайта предоставить не можем. Добавить возможность просмотра ошибок может только пользователь, который разработал данный тест. Если у Вас возникнут вопросы, напишите, пожалуйста, в нашу службу техподдержки на email: [email protected]
Обработка ошибок с помощью Python
Ошибки случаются. Написание скриптов, которое предполагает наличие и обработку ошибок, сохраняет массу времени и ваших сил. Когда инструмент выводит сообщение об ошибке, ArcPy генерирует системную ошибку или исключение. В Python вы можете обеспечить различные структуры и методы для обработки исключений. Конечно, скрипт может не выполниться по причинам, не связанным с инструментом геообработки. Их также следует обнаружить и решить. В следующих разделах предлагается несколько способов, которые ознакомят вас с основными принципами обработки исключений в Python .
Когда инструмент записывает сообщение об ошибке, ArcPy создает исключение arcpy.ExecuteError . Python позволяет написать модуль, который будет выполняться автоматически при возникновении системной ошибки. С помощью этого модуля для обработки ошибок вы сможете получать сообщения об ошибках от ArcPy и реагировать на них. Если скрипт не имеет модуля для обработки ошибок, он завершает выполнение немедленно, что уменьшает его надежность. Модуль обработки ошибок можно использовать для управления ошибками и повышения надежности скриптов.
Сообщения об ошибках в инструментах геообработки обычно имеют шестизначный код. Эти коды-идентификаторы занесены в документы, содержащие дополнительные сведения об их причинах и необходимых действиях.
Выражение try-except
Чтобы охватить всю программу целиком или только отдельные фрагменты кода для обнаружения и определения ошибок могут использоваться выражения try-except . Если в выражении try возникнет ошибка, будет создано исключение, и код будет выполнен в соответствии с выражением except. Использование выражения except является наиболее простой формой обработки ошибок.
В следующем коде Буфер не работает, потому что не был указан обязательный аргумент buffer_distance_or_field . Чтобы найти ошибку, используется выражение except , которое извлекает и выводит сообщение об ошибке, сгенерированное Буфером . Обратите внимание, что блок except выполняется только в случае, если Буфер возвращает ошибку.
import arcpy import sys try: # Execute the Buffer tool arcpy.Buffer_analysis("c:/transport/roads.shp", "c:/transport/roads_buffer.shp") except Exception: e = sys.exc_info()[1] print(e.args[0]) # If using this code within a script tool, AddError can be used to return messages # back to a script tool. If not, AddError will have no effect. arcpy.AddError(e.args[0])
Выражение try содержит необязательное условие finally , которое можно использовать для задач, которые должны выполняться всегда, независимо от того, возникает исключение или нет. В следующем примере ArcGIS 3D Analyst extension регистрируется в соответствии с условием finally , которое гарантирует, что этот дополнительный модуль всегда будет регистрироваться.
class LicenseError(Exception): pass import arcpy try: if arcpy.CheckExtension("3D") == "Available": arcpy.CheckOutExtension("3D") else: # Raise a custom exception raise LicenseError arcpy.env.workspace = "D:/GrosMorne" arcpy.HillShade_3d("WesternBrook", "westbrook_hill", 300) arcpy.Aspect_3d("WesternBrook", "westbrook_aspect") except LicenseError: print "3D Analyst license is unavailable" except arcpy.ExecuteError: print(arcpy.GetMessages(2)) finally: # Check in the 3D Analyst extension arcpy.CheckInExtension("3D")
Выражение raise
Предыдущий пример иллюстрирует ошибку в исключении, которое возникло в коде В некоторых случаях может потребоваться создать пользовательские исключения. Для этой цели может использоваться выражение raise . В следующем коде выражение raise используется, если входной класс объектов определился как не содержащий объектов. Это не обязательно ошибка, но условие, при котором код может быть использован.
class NoFeatures(Exception): pass import arcpy import os import sys arcpy.env.overwriteOutput = True fc = arcpy.GetParameterAsText(0) try: # Check that the input has features result = arcpy.GetCount_management(fc) if int(result[0]) > 0: arcpy.FeatureToPolygon_management( fc, os.path.join(os.path.dirname(fc), 'out_poly.shp')) else: # Raise custom exception raise NoFeatures(result) except NoFeatures: # The input has no features print('<> has no features'.format(fc)) except: # By default any other errors will be caught here e = sys.exc_info()[1] print(e.args[0])
Класс ExecuteError
Когда инструмент геообработки выходит из строя, он создает класс исключений arcpy.ExecuteError , что означает, что вы можете разделить ошибки на различные группы, ошибки геообработки (те, которые создают исключение arcpy.ExecuteError ) и другие типы исключений. Затем можно обрабатывать эти ошибки по разному, как показано в следующем коде:
import arcpy import sys try: result = arcpy.GetCount_management("C:/invalid.shp") # Return geoprocessing specific errors except arcpy.ExecuteError: arcpy.AddError(arcpy.GetMessages(2)) # Return any other type of error except: # By default any other errors will be caught here e = sys.exc_info()[1] print(e.args[0])
traceback
В больших и более сложных скриптах бывает сложно точное определить место возникновения ошибки. Для определения точного местоположения и причины ошибки, а также для более точного определения причины ошибки и экономии ценного времени на отладку можно использовать модули Python , sys и traceback совместно.
# Import the required modules # import arcpy import sys import traceback arcpy.env.workspace = "C:/Data/myData.gdb" try: arcpy.CreateSpatialReference_management() #-------------------------- # Your code goes here # # See the table below for examples #-------------------------- except arcpy.ExecuteError: # Get the tool error messages msgs = arcpy.GetMessages(2) # Return tool error messages for use with a script tool arcpy.AddError(msgs) # Print tool error messages for use in Python print(msgs) except: # Get the traceback object tb = sys.exc_info()[2] tbinfo = traceback.format_tb(tb)[0] # Concatenate information together concerning the error into a message string pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1]) msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n" # Return Python error messages for use in script tool or Python window arcpy.AddError(pymsg) arcpy.AddError(msgs) # Print Python error messages for use in Python / Python window print(pymsg) print(msgs)
Если был использован приведенный выше код, и произошла ошибка инструмента геообработки, такая как недопустимые входные данные, это вызовет arcpy.ExecuteError , и будет использоваться первое выражение except . Это выражение выведет сообщение об ошибке с помощью функции GetMessages . Если использовался тот же код, но возникла ошибка другого типа, будет использовано второе выражение except . Вместо печати сообщений о геообработке, будет получен объект traceback и выведены соответствующие сообщения о системных ошибках.
В таблице ниже показаны ожидаемые ошибки, являющиеся результатом трех различных строк кода, который мог быть использован вместо вышеуказанного кода. Первый пример – ошибка инструмента геообработки, которая генерирует информацию traceback и сообщения об ошибках геообработки. Второй и третий примеры не обрабатываются, а происходит только генерация данных traceback.
PYTHON ERRORS: Traceback info: File "c:\temp\errortest.py", line 10, in arcpy.GetCount_management("") Error Info: Failed to execute. Parameters are not valid. ERROR 000735: Input Rows: value is required Failed to execute (GetCount). ArcPy ERRORS: Failed to execute. Parameters are not valid. ERROR 000735: Input Rows: value is required Failed to execute (GetCount).
PYTHON ERRORS: Traceback info: File "c:\temp\errortest.py", line 10, in x = "a" + 1 Error Info: cannot concatenate 'str' and 'int' objects
float(«a text string»)
PYTHON ERRORS: Traceback info: File "c:\temp\errortest.py", line 10, in float("a text string") Error Info: invalid literal for float(): a text string
Получение сообщений об ошибках от объекта Result
Несколько слов об объекте Result , который показан ниже:
result = arcpy.GetCount_management("c:/data/rivers.shp")
Если запрос в GetCount_management вызывает исключение, объект Result не создается. Это означает, что вы не можете получать сообщения об ошибках от объекта Result .
import arcpy try: result = arcpy.GetCount_management("c:/data/rivers.shp") # Return Geoprocessing specific errors # (this method is incorrect!) except arcpy.ExecuteError: arcpy.AddError(result.getMessages(2))
Указанный выше код не работает, и появляется сообщение name ‘result’ is not defined . Причина в том, что объект Result невозможно было создать из-за ошибки инструмента. Поскольку объект Result не создан, возникает ошибка Python при попытке использования метода getMessages .
Примечание:
Объект Result , создаваемый путем запроса в сервис геообработки на ArcGIS Server , создается даже при ошибке инструмента. Создание объекта Result не удается только тогда, когда инструмент запускается локально и вызывает ошибку. Более подробную информацию об использовании объекта result смотрите в разделе Использование инструментов в Python .
В этом разделе
- Выражение try-except
- Выражение raise
- Класс ExecuteError
- traceback
- Получение сообщений об ошибках от объекта Result