Вместе с факультетом Python-разработки GeekUniversity собрали для вас несколько простых задач по Python для обучения и тренировки. Их можно решать в любом порядке.
Обратите внимание, что у любой задачи по программированию может быть несколько способов решения. Чтобы посмотреть добавленный нами вариант решения, кликните по соответствующей кнопке. Все приведённые варианты написаны на Python 3.
Есть список a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
.
Выведите все элементы, которые меньше 5
.
Вариант решения
Самый простой вариант, который первым приходит на ум — использовать цикл for
:
for elem in a: if elem < 5: print(elem)
Также можно воспользоваться функцией filter
, которая фильтрует элементы согласно заданному условию:
print(list(filter(lambda elem: elem < 5, a)))
И, вероятно, наиболее предпочтительный вариант решения этой задачи — списковое включение:
print([elem for elem in a if elem < 5])
Даны списки:
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
;
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
.
Нужно вернуть список, который состоит из элементов, общих для этих двух списков.
Вариант решения
Можем воспользоваться функцией filter
:
result = list(filter(lambda elem: elem in b, a))
Или списковым включением:
result = [elem for elem in a if elem in b]
А можно привести оба списка к множествам и найти их пересечение:
result = list(set(a) & set(b))
Однако в таком случае каждый элемент встретится в результирующем списке лишь один раз, т.к. множество поддерживает уникальность входящих в него элементов. Первые два решения (с фильтрацией) оставят все дубли на своих местах.
Отсортируйте словарь по значению в порядке возрастания и убывания.
Вариант решения
Импортируем нужный модуль и объявляем словарь:
import operator d = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
Сортируем в порядке возрастания:
result = dict(sorted(d.items(), key=operator.itemgetter(1)))
И в порядке убывания:
result = dict(sorted(d.items(), key=operator.itemgetter(1), reverse=True))
Напишите программу для слияния нескольких словарей в один.
Вариант решения
Допустим, вот наши словари:
dict_a = {1:10, 2:20} dict_b = {3:30, 4:40} dict_c = {5:50, 6:60}
Объединить их можно вот так:
result = {} for d in (dict_a, dict_b, dict_c): result.update(d)
А можно с помощью «звёздочного» синтаксиса:
result = {**dict_a, **dict_b, **dict_c}
О звёздочном синтаксисе можно прочитать в нашей статье.
Найдите три ключа с самыми высокими значениями в словаре my_dict = {'a':500, 'b':5874, 'c': 560,'d':400, 'e':5874, 'f': 20}
.
Вариант решения
Можно воспользоваться функцией sorted
:
result = sorted(my_dict, key=my_dict.get, reverse=True)[:3]
Аналогичный результат можно получить с помощью функции nlargest
из модуля heapq
:
from heapq import nlargest result = nlargest(3, my_dict, key=my_dict. get)
Читайте также: Всё о сортировке на Python
Напишите код, который переводит целое число в строку, при том что его можно применить в любой системе счисления.
Вариант решения
Второй аргумент функции int
отвечает за указание основания системы счисления:
print(int('ABC', 16))
Нужно вывести первые n строк треугольника Паскаля. В этом треугольнике на вершине и по бокам стоят единицы, а каждое число внутри равно сумме двух расположенных над ним чисел.
Вариант решения
def pascal_triangle(n): row = [1] y = [0] for x in range(max(n, 0)): print(row) row = [left + right for left, right in zip(row + y, y + row)] pascal_triangle(6)
Напишите проверку на то, является ли строка палиндромом. Палиндром — это слово или фраза, которые одинаково читаются слева направо и справа налево.
Вариант решения
Тут всё просто, достаточно сравнить строку с её обратной версией, для чего можно использовать встроенную функцию reversed:
def is_palindrome(string): return string == ''. join(reversed(string)) print(is_palindrome('abba'))
Того же эффекта можно добиться с помощью срезов:
def is_palindrome(string): return string == string[::-1] print(is_palindrome('abba'))
Сделайте так, чтобы число секунд отображалось в виде дни:часы:минуты:секунды
.
Вариант решения
def convert(seconds): days = seconds // (24 * 3600) seconds %= 24 * 3600 hours = seconds // 3600 seconds %= 3600 minutes = seconds // 60 seconds %= 60 print(f'{days}:{hours}:{minutes}:{seconds}') convert(1234565)
Вы принимаете от пользователя последовательность чисел, разделённых запятой. Составьте список и кортеж с этими числами.
Вариант решения
values = input('Введите числа через запятую: ') ints_as_strings = values.split(',') ints = map(int, ints_as_strings) lst = list(ints) tup = tuple(lst) print('Список:', lst) print('Кортеж:', tup)
Выведите первый и последний элемент списка.
Вариант решения
lst = [1, 2, 3, 4, 5] print(f'Первый: {lst[0]}; последний: {lst[-1]}')
Напишите программу, которая принимает имя файла и выводит его расширение. Если расширение у файла определить невозможно, выбросите исключение.
Вариант решения
def get_extension(filename): filename_parts = filename.split('.') if len(filename_parts) < 2: # filename has no dots raise ValueError('the file has no extension') first, *middle, last = filename_parts if not last or not first and not middle: # example filenames: .filename, filename., file.name. raise ValueError('the file has no extension') return filename_parts[-1] print(get_extension('abc.py')) print(get_extension('abc')) # raises ValueError print(get_extension('.abc')) # raises ValueError print(get_extension('.abc.def.')) # raises ValueError
При заданном целом числе n посчитайте n + nn + nnn.
Вариант решения
def solve(n): n1 = n n2 = int(str(n) * 2) n3 = int(str(n) * 3) print(n1 + n2 + n3) solve(5)
Напишите программу, которая выводит чётные числа из заданного списка и останавливается, если встречает число 237.
Вариант решения
numbers = [ 386, 462, 47, 418, 907, 344, 236, 375, 823, 566, 597, 978, 328, 615, 953, 345, 399, 162, 758, 219, 918, 237, 412, 566, 826, 248, 866, 950, 626, 949, 687, 217, ] for x in numbers: if x == 237: break elif x % 2 == 0: print(x)
Напишите программу, которая принимает два списка и выводит все элементы первого, которых нет во втором.
Вариант решения
set_1 = set(['White', 'Black', 'Red']) set_2 = set(['Red', 'Green']) print(set_1 - set_2)
Выведите список файлов в указанной директории.
Вариант решения
from os import listdir from os.path import isfile, join files = [f for f in listdir('/home') if isfile(join('/home', f))] print(files)
Сложите цифры целого числа.
Вариант решения
def sum_digits(num): digits = [int(d) for d in str(num)] return sum(digits) print(sum_digits(5245))
Посчитайте, сколько раз символ встречается в строке.
Вариант решения
string = 'Python Software Foundation' string.count('o')
Поменяйте значения переменных местами.
Вариант решения
Можно написать монструозную конструкцию в стиле языка C:
x = 5 y = 10 temp = x x = y y = temp
Но в Python есть более удобный способ для решения этой задачи:
x = 5 y = 10 x, y = y, x
С помощью анонимной функции извлеките из списка числа, делимые на 15.
Вариант решения
nums = [45, 55, 60, 37, 100, 105, 220] result = list(filter(lambda x: not x % 15, nums))
Нужно проверить, все ли числа в последовательности уникальны.
Вариант решения
def all_unique(numbers): return len(numbers) == len(set(numbers))
Напишите программу, которая принимает текст и выводит два слова: наиболее часто встречающееся и самое длинное.
Вариант решения
import collections text = 'lorem ipsum dolor sit amet amet amet' words = text.split() counter = collections.Counter(words) most_common, occurrences = counter.most_common()[0] longest = max(words, key=len) print(most_common, longest)
Хотите вырасти от новичка до профессионала? Факультет Python-разработки GeekUniversity даёт год опыта для вашего резюме. Обучайтесь на практических заданиях, по-настоящему освойте Python и станьте ближе к профессии мечты.
Узнать больше
Python (или, как его еще называют, «питон») – популярный и перспективный язык. Его часто выбирают в качестве первого для знакомства с программированием. Изучать Python мы будем с нуля, с самых азов. Первый модуль – плацдарм для написания осмысленных программ. В нем мы разберем, как дать команду компьютеру на языке Python. Расскажем, что такое комментарии и зачем они нужны. На примере проверки ваших решений на сайте рассмотрим, что такое тестирование и как читать вывод тестов. Объясним, почему нельзя нарушать грамматические правила языка программирования.
Современные программы создаются для обслуживания бизнесов, помощи в ежедневной жизни и развлечений. Но в основе их работы по-прежнему лежат вычисления. Наиболее простая и базовая тема в программировании — арифметика. В этом модуле мы переведем арифметические действия на язык программирования, освоим базовую терминологию – например, чем оператор отличается от операнды. Поговорим о приоритете операций. А под конец расскажем, что такое линтер и почему он может «ругаться».
Текст в программировании называется «строками», и эта тема не так проста, как может показаться. Как вывести фразу, в которой есть и одинарные, и двойные кавычки? Что такое экранированная последовательность? Модуль посвящен разным аспектам написания текста – мы поэкспериментируем с выводом разных строк и поговорим о кодировке.
Информацию можно помещать в специальные «хранилища», а потом использовать сколько угодно раз. Эти хранилища называются переменными, и они помогают упростить код и сократить лишние повторения.
Продолжаем изучать строки и их связь с переменными. Разбираем интерполяцию, извлечение символов, слайсы и другое
Python – язык с сильной типизацией и неизменяемыми примитивными типами данных. Что произойдет, если мы попробуем умножить число на строку? Каким образом Python понимает, что за тип данных перед ним? Что такое преобразование типов? Ответы на эти вопросы вы найдете в текущем модуле.
Начните прямо сейчас
Регистрация
Для выражения любой произвольной операции в программировании существует понятие «функция». Функции — кирпичики, из которых программисты строят системы. В этом модуле мы научимся пользоваться уже созданными функциями. Посмотрим на сигнатуру функции в документации и разберемся, как её использовать. Познакомимся со стандартными библиотеками, которые хранят тысячи функций. Все функции невозможно выучить, но каждый программист должен знать, где искать документацию по ним.
Данные, которыми мы оперируем в своих программах, могут обладать важными атрибутами. В Python атрибуты встроены прямо в язык. Кроме статических свойств у данных существуют методы — функции, находящиеся внутри свойств. Свойства и методы — такие же выражения, как переменные или вызовы функции, а значит, их можно всячески комбинировать. Глубже эти темы разбираются на отдельных курсах, посвященных объектно-ориентированным возможностям Python. Мы же в этом модуле изучим основы.
Определение собственных функций значительно упрощает написание и поддержку программ. Например, умение определять функции позволяет объединять сложные (составные) операции в одну – вся сложность может быть скрыта за одной простой функцией. Научившись писать функции, вы сделаете первый шаг на пути к построению по-настоящему полезных программ. И мы вам в этом поможем. В этом модуле вы создадите свою первую функцию и научитесь давать ей название, которое поймет любой разработчик.
Логические выражения позволяют отвечать на вопросы, которые возникают во время работы программы. Пользователь аутентифицирован? Подписка оплачена? Год високосный? В этом модуле изучаем функции-предикаты – те, которые задают вопрос и отвечают на него – правда это или ложь. Попрактикуемся в написании таких функций и перейдем к более сложным логическим выражениям.
Задача функции-предиката — получить ответ на вопрос, но обычно этого недостаточно и нужно выполнить определенное действие в зависимости от ответа. If и if-else – конструкции Python, с помощью которых программист может выбирать необходимое поведение программы в зависимости от разных условий: пропускать одни инструкции и выполнять другие. Их и разберем на практике в этом модуле.
Любой код может повторяться десятки, тысячи, миллионы раз. В комбинации с другими известными нам инструментами — переменными и условиями — это открывает множество возможностей по построению программ и сложных систем. Приведем простой пример. Вам нужно найти конкретную фразу в учебнике из 500 страниц. Фразу вы помните, а вот номер страницы нет. Самый простой (и долгий) способ — последовательно просматривать страницы до тех пор, пока не найдете нужную. Для выполнения таких повторяющихся действий и нужны циклы.
Готовы попробовать?
Регистрация не требуется
Демо урок
Посмотреть все курсы категории Программирование
C++
7 часов3689
Rust
0 часов432
Fortran
0 часов544
Kotlin
3 часа923
Нравится (5)
Твитнуть
Делиться
8. 59К Просмотров
Безопасность программного обеспечения является важной темой, которая на протяжении многих лет находится в центре внимания многих исследователей и специалистов. Одной из причин, по которой эта тема не теряет актуальности, является количество уязвимостей, которые становятся известны каждый день. Согласно NVD (2006), уязвимость можно определить как «слабость вычислительной логики (например, кода), обнаруженную в программных и аппаратных компонентах, которая при использовании приводит к негативному влиянию на конфиденциальность, целостность или доступность». Цифры, окружающие этот тип вычислительной проблемы, дают более конкретное представление о ее критичности. Seacord (2013) утверждает, что за девять лет — с 2004 по 2012 год — в Национальной базе данных уязвимостей (NVD) Национального института стандартов и технологий (NIST) было зарегистрировано и каталогизировано 45 135 уязвимостей. При этом только в 2019 г., в НВД поступило 18 938 новых записей.
С точки зрения безопасного программирования, злоумышленники использовали две категории уязвимостей, чтобы нарушить правильность работы программного обеспечения. Первая — это уязвимости, связанные со строками. По сути, сбои этой категории вызывают своего рода угрозу безопасности, известную как переполнение буфера. Еще одна распространенная категория уязвимостей связана с Integer. Наиболее распространенными ошибками, обнаруженными в этой категории, являются ошибки переполнения и знаковые ошибки. Все эти ситуации могут привести к неожиданному поведению, и система может оказаться в незащищенном состоянии. В подобных сценариях стратегии смягчения последствий, направленные на то, чтобы не поставить под угрозу программу или даже всю систему, обычно основаны на твердом знании используемого языка программирования и тщательном изучении его ресурсов.
При правильной и точной работе со строками в языке программирования C необходимо учитывать, что строка представляет собой последовательность символов, заканчивающуюся нулем. Неточное понимание этого представления String обычно приводит к некоторым из наиболее распространенных ошибок: неограниченным копиям строк, ошибкам «не за единицей», ошибкам нулевого завершения и усечению строки. Фрагмент кода ниже показывает типичный пример неограниченной копии строки. Программа готова принимать не более восьми символов со стандартного ввода ( стандартный номер ). Тем не менее, использование функции gets() не позволяет ограничить количество символов, вводимых пользователем. Из-за этого злоумышленник может исследовать эту проблему, введя более восьми символов и передав их программе. Поскольку в этом сценарии нуль-терминатор перекрывается, другие ячейки памяти, не выделенные программой, используются для хранения дополнительных символов, которые могут привести к неожиданному поведению программы.
С другой стороны, второй код ниже описывает практический пример, в котором имеет место ошибка «не на единицу». Так же, как и неограниченные копии строк, ошибки «выход за один» связаны с выводом символов за пределы строки. В таком примере строка длины 10 корректно хранится в переменной источник , емкость памяти которого точно определена. Уязвимость начинается с выделения памяти для строки dest . В этой операции используется функция strlen , которая подсчитывает количество символов в строке до тех пор, пока не найдет нуль-терминатор. Таким образом, для строки dest не резервируется позиция для символа, отвечающего за указание на завершение строки. Как цикл, копирующий символы из строки источника в строку dest начинается с позиции 1, последняя команда записывает нулевой символ за пределы строки dest . Устанавливается ошибка «один за другим», и программа может вести себя непредсказуемым образом.
Большинство ошибок и уязвимостей при манипулировании целыми числами связано с недостаточной проверкой пределов переменных, хранящих данные этого типа. В приведенном ниже коде представлена распространенная ошибка, вызванная неточным преобразованием типов (Seacord, 2013). Хотя функция проверяет, были ли информированы размер значение параметра соответствует пределу максимального размера массива, нет проверки, связанной с сигналом значения параметра. Таким образом, переданный функции отрицательный размер будет считаться разрешенным, и функция malloc будет вызвана с отрицательным значением. Поскольку malloc ожидает аргументы типа size_t , он преобразует значение размера в большое число без знака, что может привести к значению, большему, чем определено в MAX_ARRAY_SIZE .
Еще одна типичная ситуация, которая может привести к ошибкам, связанным с целыми числами, упоминалась Dannenberg et al (2010) как перенос целых чисел без знака. В следующем коде показан фрагмент кода, описывающий такую ситуацию. Поскольку сценарий связан с пользовательской структурой данных (), внутренние вычисления, обернутые функцией, могут привести к тому, что объем памяти будет меньше, чем требуется для хранения структуры данных. Прямым следствием является ошибка переполнения буфера
Согласно Куперману и др. (2005), «один из лучших способов предотвратить использование уязвимостей, связанных с переполнением буфера, — это обнаружить и устранить их из исходного кода до того, как программное обеспечение будет использовано». Принимая во внимание уязвимости, представленные в первых двух приведенных выше кодах, первую можно было бы напрямую смягчить, изменив использование функции gets на fgets в соответствии с рекомендациями Института программной инженерии (2007). Эта альтернативная функция «считывает не более чем на один символ меньше указанного числа из потока в массив». Второй можно исправить, учитывая положение нулевого терминатора при выделении строки и корректируя индексы, определенные для цикла, отвечающего за копирование символов. В приведенном ниже коде показана исправленная ошибка смещения на единицу.
Образцы уязвимостей, связанные с целыми числами, описанные в двух других частях кода, также можно обойти с помощью очень пунктуальных решений. Проблема ошибки преобразования устраняется простым изменением типа параметра size с int на size_t , поскольку последний гарантирует точную точность представления размера любой структуры данных (CPP Reference, 2020). . Решение для описанной выше ситуации переноса целых чисел без знака предложено Dannenberg et al (2010). Авторы поясняют, что экземпляр std::bad_array_new_length должен быть выброшен, чтобы сообщить о целочисленном переполнении.
Этот анализ как строковых, так и целочисленных уязвимостей показал, что многих связанных с этим ошибок можно было бы избежать за счет более аккуратной работы программирования и использования определенных ресурсов языка программирования в соответствующих сценариях. Кроме того, внедрение некоторых методов программирования могло бы способствовать разработке более надежного программного обеспечения. Как заявил Данненберг и др. (2010), предварительное тестирование — это подход, который можно использовать для устранения многих случаев целочисленных уязвимостей. Однако та же самая стратегия также может решить многие ошибки, связанные со строками, поскольку проверка границ строки, задействованной в выполняемых операциях, позволяет избежать некоторых проблем с переполнением буфера.
Типы данных Струны Уязвимость
Опубликовано в DZone с разрешения Тьяго Насименто. Смотрите оригинальную статью здесь.
Мнения участников DZone являются их собственными.
[Опрос DZone] Поделитесь своим опытом для нашего исследования контейнеров 2023 года
Адаптация Web3 ужасна: как сделать ее лучше с помощью абстракции аккаунта и потока
5 лучших фреймворков Java для веб-разработки в 2023 году
Шифрование данных: преимущества, типы и методы