пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
По вашему запросу ничего не найдено :(
Убедитесь, что запрос написан правильно, или посмотрите другие
наши статьи:
100 примеров, с помощью которых вы сможете рационализировать ваш обычный рабочий процесс.
Python славится свой простотой и легкостью в изучении. Эти два фактора делают его идеальным вариантом для разработчиков любого уровня квалификации. Здесь я составил полезный список однострочников Python, с которыми, вы, скорее всего, будете сталкиваться, работая над своими обычными задачами разработки. Все эти однострочники являются практическими решениями самых распространённых задач, и, я думаю, что вы сочтете их для себя крайне полезными. Этот список никак не структурирован, так что не стесняйтесь изучать его в удобное для вас время. Без лишних слов, давайте окунемся в эту тему и откроем для себя магию однострочников Python, которые, без каких-либо сомнений, упростят процесс написания кода и дадут вам возможности для решения ваших повседневных задач!
Создание нового списка с помощью кода в одну строку
squares = [x**2 for x in range(10)]
Генерирует список квадратов целых чисел от 0 до 9
Создание нового списка, содержащего элементы, которые соответствуют условию
evens = [x for x in range(10) if x % 2 == 0]
Генерирует список четных в диапазоне от 0 до 9
Лямбда-функция
Определим небольшую анонимную функцию
add = lambda x, y: x + y
Создает простую функцию для сложения двух чисел
Фильтрация списка
Создадим новый список из элементов, удовлетворяющих условию
evens = [x for x in range(10) if x % 2 == 0]
Генерирует список четных чисел из диапазона от 0 до 9
(CSV-файл)
Функция map
Применим функцию к каждому итерируемому элементу
squares = list(map(lambda x: x**2, range(10)))
Функция filter
Профильтруем итерируемые элементы с учетом условия
evens = list(filter(lambda x: x % 2 == 0, range(10)))
Генерирует список четных цифр от 0 до 9 с помощью функции
filter
Переворот строки
Поменяем порядок символов в строке
reversed_string = 'Hello, World!'[::-1]
Переворачивает строку «Hello, world!» в строку «!dlrow ,olleH»
Цепочка сравнений
Проверим выполнение нескольких сравнений
x < y < z
Проверяет, что «x» меньше «y», а «y» меньше «z»
Тернарный оператор
Присвоим значение с учетом условия
x = a if condition else b
Присваивает переменной «х» значение «а», если условие верно, в противном случае – «b»
Перечисление списка
Переберем список по индексу и значению.
for i, item in enumerate(my_list):
Проходит по списку «my_list» и получает доступ как к индексу, так и к значению
«Упаковка» списков
Объединим элементы нескольких списков попарно
for a, b in zip(list_a, list_b):
Проходит по спискам «list_a» и «list_b», объединяя в пары числа с одинаковыми индексами
Сведение списка, состоящего из списков
Объединим элементы вложенных списков в один
flat_list = [item for sublist in list_of_lists for item in sublist]
Сводит «list_of_lists» в один единый список «flat_list»
# Sample data { # Выборочные данные }
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9, 10]]
# Flatten the list { # Сводим список }
flat_list = [item for sublist in list_of_lists for item in sublist]
# Output { # Результат }
print(flat_list)
#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Перестановка значений переменных
Поменяем значения двух переменных
a, b = b, a
Меняет значения переменных «а» и «b»
Преобразование списка из строк в одну строку
Соединим элементы списка в одну единую строку
s = ' '.join(['hello', 'world'])
Объединяет элементы списка в строку «hello world»
Поиск индекса максимального значения в списке
max_index = max(range(len(my_list)), key=my_list.__getitem__)
Ищет индекс максимального значения в списке «my_list»
Поиск максимального значения и его индекса в списке
max_value, max_index = max((val, idx) for idx, val in enumerate(my_list))
Ищет максимальное значение и его индекс в списке «my_list»
Поиск минимального значения и его индекса в списке
`min_value, min_index = min((val, idx) for idx, val in enumerate(my_list))`
Ищет минимальное значение и его индекс в списке «my_list»
Печать списка через запятую
print(*my_list, sep=', ')
Печатает элементы списка «my_list» через запятую
Вычисление факториала
import math; math.factorial(5)
Вычисляет факториал числа 5
Вычисление n-го числа Фибоначчи
fib = lambda n: n if (n <= 1) else (fib(n-1) + fib(n-2))
Определяет лямбда-функцию для вычисления n-го числа Фибоначчи
Подсчет количество вхождений элемента в список
count = my_list.count(element)
Подсчитывает количество вхождений значений «element» в список «my_list»
Удаление дубликатов из списка
unique_list = list(set(my_list))
Создает список «unique_list» с дубликатами, удаленными из списка «my_list»
Сортировка списка по пользовательскому ключу
Отсортируем список по конкретному атрибуту или функции
sorted_list = sorted(my_list, key=lambda x: x[1])
Сортирует список «my_list» по второму элементу каждого элемента списка
Проверка, удовлетворяют ли все элементы условию
all(x > 0 for x in my_list)
Проверяет, все ли элементы списка «my_list» больше, чем 0
Проверка, удовлетворяют ли какие-нибудь элементы условию
Проверим, все ли элементы в итерируемом списке соответствуют условию
any(x > 0 for x in my_list)
Проверяет, все ли элементы списка «my_list» больше, чем 0
(CSV-файл)
Преобразование списка кортежей в словарь
Преобразуем список пар ключ-значение в словарь
my_dict = dict([('a', 1), ('b', 2), ('c', 3)])
Создает словарь из списка кортежей
Печать форматированной строки
Воспользуемся f-строкой для печати переменных в строке
print(f'Hello, {name}!')
Печатает строку с включенной переменной «name»
Создание псевдонима функции
Присвоим существующую функцию к новому имени
alias = original_function
Создает псевдоним для функции «original_function»
Поиск самого распространенного элемента в списке
most_common = max(set(my_list), key=my_list.count)`
# Sample data { # Выборочные данные }
my_list = [1, 2, 3, 3, 3, 4, 4, 5, 5, 5, 5]
# Find the most common element { # Находим самый распространенный элемент }
most_common = max(set(my_list), key=my_list.count)
# Output { # Результат }
print(most_common)
# 5
Ищет самый часто встречающийся элемент в списке «my_list»
(CSV-файл)
Ввод в виде списка целых чисел
Прочитаем строку ввода и преобразуем ее в список целых чисел
numbers = list(map(int, input().split()))
Преобразует пользовательский ввод в список целых чисел под названием «numbers»
# Prompt the user to enter a space-separated string of numbers { # Предлагаем пользователю ввести строку чисел, разделенных пробелом }
input_string = input("Enter some numbers separated by spaces: ")
# Convert the string to a list of integers { # Преобразовываем строку в список целых чисел }
numbers = list(map(int, input_string.split()))
# Output the list of numbers { # Выводим список чисел }
print(numbers)
#Enter some numbers separated by spaces: 10 20 30 40 50 { # Вводим некоторые числа через пробелы: 10 20 30 40 50 }
#[10, 20, 30, 40, 50]
Транспонирование матрицы
Перевернем матрицу относительно ее диагонали
transposed = list(zip(*matrix))
Транспонирует матрицу и сохраняет результат в переменной «transposed»
# Sample data { # Выборочные данные }
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# Transpose the matrix { # Транспонируем матрицу }
transposed = list(zip(*matrix))
# Output { # Результат }
print(transposed)
#[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
Проверка строки, является ли она палиндромом
Проверим, читается ли строка справа налево так же, как и слева направо
is_palindrome = s == s[::-1]
Проверяет, является ли строка «s» палиндромом
# Sample data { # Выборочные данные }
s = "racecar"
# Check if the string is a palindrome { # Проверяем, является ли строка палиндромом }
is_palindrome = s == s[::-1]
# Output { # Результат }
print(is_palindrome)
#True
Слияние двух словарей
Объединим два словаря путем обновления значений второго словаря
merged_dict = {**dict1, **dict2}
Объединяет словари «dict1» и «dic2» в один словарь «merged_dict»
Сумма элементов списка
Подсчитаем сумму элементов списка
total = sum(my_list)
Считает сумму элементов списка «my_list»
Вычисление среднего значения списка
Подсчитаем среднее значение элементов списка
average = sum(my_list) / len(my_list)
Считает среднее значение элементов списка «my_list»
Ввод в виде списка чисел с плавающей точкой
Прочитаем строку ввода и преобразуем ее в список чисел с плавающей точкой
floats = list(map(float, input().split()))
Преобразует пользовательский ввод в список чисел с плавающей точкой под названием «floats»
# Prompt the user to enter a space-separated string of numbers { # Предлагаем пользователю ввести строку чисел, разделенных пробелами }
input_string = input("Enter some floating-point numbers separated by spaces: ")
# Convert the string to a list of floats { # Преобразуем строку в список чисел с плавающей точкой }
floats = list(map(float, input_string.split()))
# Output the list of floats { # Выводим список чисел с плавающей точкой }
print(floats)
#Enter some floating-point numbers separated by spaces: 3.14 2.718 1.414 0.577 { # Вводим некоторые числа с плавающей точкой через пробелы: 3.14 2.718 1.414 0.577 }
#[3.14, 2.718, 1.414, 0.577]
Сортировка списка строк по их длине
Организуем список строк с учетом их длин
sorted_strings = sorted(my_list, key=len)
Сортирует список «my_list» по длине его строк
Преобразование строки в список символов
Разделим строку и получим список отдельных символов
char_list = list('hello')
Преобразует строку «hello» в список символов
# Convert a string to a list of characters { # Преобразовываем строку в список символов }
char_list = list('hello')
# Output the list of characters { # Выводим список символов }
print(char_list)
#['h', 'e', 'l', 'l', 'o']
Разделение строки по пробелам
Разделим строку по пробелам и получим список слов
words = s.split()
Разделяет строку «s» в список слов
# Sample data { # Выборочные данные }
s = "This is a sentence."
# Split the string into words { # Разделяем строку на слова }
words = s.split()
# Output the list of words { # Выводим список слов }
print(words)
#['This', 'is', 'a', 'sentence.']
(CSV_файл)
Конкатенация списка, состоящего из списков
Объединим несколько списков в один
merged_list = sum(list_of_lists, [])
Конкатенирует список, состоящий из списков, в один список под названием «merged_list»
# Sample data { # Выборочные данные }
list_of_lists = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]
# Flatten the list of lists { # Объединяем список, состоящий из списков }
merged_list = sum(list_of_lists, [])
# Output the merged list { # Выводим объединенный список }
print(merged_list)
#[1, 2, 3, 4, 5, 6, 7, 8, 9]
Проверка числа на простоту
Проверим, делится ли число только на 1 и на самого себя
is_prime = all(n % i for i in range(2, int(n**0.5) + 1))
Проверяет, является ли число «n» простым
# Sample data { # Выборочные данные }
n = 17
# Check if the number is prime { # Проверяем, является ли число простым }
is_prime = all(n % i for i in range(2, int(n**0.5) + 1))
# Output the result { # Выводим результат }
print(is_prime)
#True
Создание диапазона чисел с заданным шагом
Сгенерируем диапазон чисел с заданным размером шага
my_range = list(range(0, 10, 2))
Создает список четных чисел от 0 до 9
Преобразование строки в нижний/верхний регистр
Преобразуем символы строки в нижний регистр
lower_string = s.lower()
upper_string = s.upper()
Преобразует строку «s» в нижний регистр
Создание списка кортежей из нескольких списков
Сгенерируем список кортежей путем объединения элементов из нескольких списков
tuples_list = list(zip(list1, list2))
Создает список кортежей путем объединения элементов из списков «list1» и «list2»
# Sample data { # Выборочные данные }
list1 = ['a', 'b', 'c']
list2 = [1, 2, 3]
# Combine the two lists into a list of tuples { # Объединяем два списка с один список кортежей }
tuples_list = list(zip(list1, list2))
# Output the list of tuples { # Выводим список кортежей }
print(tuples_list)
# [('a', 1), ('b', 2), ('c', 3)]
Проверка строки на наличие подстроки
Проверим, содержит ли строка другую строку
substring_present = substring in main_string
Проверяет, содержит ли строка «main_string» подстроку «substring»
Разделение строки по определенному символу
Разобьем строку в список подстрок по определенному символу
split_list = s.split(',')
Делит строку «s» в список подстрок по запятым
Поэлементное сложение двух списков
Объединим два списка путем сложения соответствующих элементы вместе
combined_list = [a + b for a, b in zip(list1, list2)]
Создаем список «combined_list», складывая элементы из списков «list1» и «list2»
# Sample data { # Выборочные данные }
list1 = [1, 2, 3]
list2 = [10, 20, 30]
# Combine the two lists element-wise { # Объединяем два списка поэлементно }
combined_list = [a + b for a, b in zip(list1, list2)]
# Output the combined list { # Выводим объединенный список }
print(combined_list)
#[11, 22, 33]
Поиск уникальных элементов в списке
Выведем различные элементы списка с сохранением порядка
unique_list = list(dict.fromkeys(my_list))
Создает список «unique_list» с уникальными элементами из списка «my_list», сохраняя порядок
# Sample data { # Выборочные данные }
my_list = [1, 2, 2, 3, 3, 3, 4, 5, 5]
# Remove duplicates from the list { # Удаляем дубликаты из списка }
unique_list = list(dict.fromkeys(my_list))
# Output the unique list { # Выводим список уникальных значений }
print(unique_list)
#[1, 2, 3, 4, 5]
Для создания нового словаря мы используем метод
dict.fromkeys()
, поскольку в словаре не может быть повторяющихся ключей, а этот метод эффективно удаляет дубликаты из списка
my_list
.
Получение длины списка без использования len()
Подсчитаем количество элементов в списке без применения функции len()
list_length = sum(1 for _ in my_list)
Вычисляет длину списка «my_list» без использования функции len()
# Sample data { # Выборочные данные }
my_list = ['a', 'b', 'c', 'd', 'e']
# Count the number of elements in the list { # Подсчитываем количество элементов в списке }
list_length = sum(1 for _ in my_list)
# Output the list length { # Выводим длину списка }
print(list_length)
#5
Поиск различий в двух списках
Выведем элементы, которые есть только в одном из двух списков
difference = list(set(list1) - set(list2))
Ищет различия межу списками «list1» и «list2»
# Sample data { # Выборочные данные }
list1 = [1, 2, 3, 4, 5]
list2 = [3, 4, 5, 6, 7]
# Find the difference between the two lists { # Ищем различия между двумя списками }
difference = list(set(list1) - set(list2))
# Output the difference { # Выводим различия }
print(difference)
#[1, 2]
Создание списка символов из строки без пробелов
Сгенерируем список символов из строки, исключив пробелы
char_list = [c for c in s if c != ' ']
Создает список символов из строки «s», пропуская пробелы
# Sample data { # Выборочные данные }
s = "The quick brown fox"
# Remove spaces from the string { # Удаляем пробелы из строки }
char_list = [c for c in s if c != ' ']
# Output the list of characters { # Выводим список символов }
print(char_list)
#['T', 'h', 'e', 'q', 'u', 'i', 'c', 'k', 'b', 'r', 'o', 'w', 'n', 'f', 'o', 'x']
Замена всех вхождений подстроки в строку
Заменим все экземпляры подстроки в строке другой строкой
new_string = s.replace(old_substring, new_substring)
Заменяет все вхождения подстроки «old_substring» в строку «s» новой подстрокой «new_substring»
# Sample data { # Выборочные данные }
s = "The quick brown fox jumps over the lazy dog."
old_substring = "fox"
new_substring = "cat"
# Replace the old substring with the new substring { # Заменяем старую подстроку новой }
new_string = s.replace(old_substring, new_substring)
# Output the new string { # Выводим новую строку }
print(new_string)
#The quick brown cat jumps over the lazy dog.
Разделение строки на список строк
lines = s.splitlines()
Делит строку «s» и преобразует в список строк
Создание строки из списка символов
my_string = ''.join(char_list)
Конкатенирует список символов в строку
# Sample data { # Выборочные данные }
char_list = ['T', 'h', 'e', ' ', 'q', 'u', 'i', 'c', 'k', ' ', 'b', 'r', 'o', 'w', 'n', ' ', 'f', 'o', 'x']
# Concatenate the list of characters into a string { # Конкатенируем список символов в строку }
my_string = ''.join(char_list)
# Output the resulting string { # Выводим получившуюся строку }
print(my_string)
#The quick brown fox
Получение последнего элемента списка
last_element = my_list[-1]
Извлекает последний элемент списка «my_list»
(CSV-файл)
Поворот списка с n-ой позиции
rotated_list = my_list[-n:] + my_list[:-n]
Разворачивает список «my_list» с n-ой позиции
# Sample data { # Выборочные данные }
my_list = [1, 2, 3, 4, 5]
n = 2
# Rotate the list by n positions to the left { # Переворачиваем список со смещением на n позиций влево }
rotated_list = my_list[-n:] + my_list[:-n]
# Output the rotated list { # Выводим перевернутый список }
print(rotated_list)
#[3, 4, 5, 1, 2]
Вырезка массива
sliced_list = my_list[start:stop:step]
Вырезает часть массива с помощью значений «start», «stop» и «step»
Получение кода символа в ASCII
ascii_value = ord(char)
#Find the ASCII value of the character ‘char’ { # Найдем код ASCII символа char }
# Sample data { # Выборочные данные }
char = 'A'
# Get the ASCII value of the character { # Получаем код ASCII символа char }
ascii_value = ord(char)
# Output the ASCII value { # Выводим код ASCII }
print(ascii_value)
#65
Подсчет количества слов в строке
len(string.split())
string = "This is a sample string for demonstration purposes"
word_count = len(string.split())
print(f"The string '{string}' contains {word_count} words.")
#The string 'This is a sample string for demonstration purposes' contains 8 words. { # Строка «This is a sample string for demonstration purposes» содержит 8 слов. }
Перемешивание списка
import random; random.shuffle(list)
import random
# Create a list of numbers from 1 to 10 { # Создадим список чисел от 0 до 10 }
my_list = list(range(1, 11))
print("Original list:", my_list)
# Shuffle the list { # Перемешаем список }
random.shuffle(my_list)
print("Shuffled list:", my_list)
#Original list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] { # Первоначальный список: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }
#Shuffled list: [6, 10, 3, 9, 8, 5, 2, 4, 7, 1] { # Перемешанный список: [6, 10, 3, 9, 8, 5, 2, 4, 7, 1] }
Генерация всех возможных комбинаций элементов списка
import itertools; [list(comb) for i in range(len(list)+1) for comb in itertools.combinations(list, i)]
import itertools
# Define a list of letters { # Определим список букв }
my_list = ['a', 'b', 'c']
# Generate all possible combinations of the letters { # Сгенерируем все возможные комбинации этих букв }
combinations = [list(comb) for i in range(len(my_list)+1) for comb in itertools.combinations(my_list, i)]
# Print the combinations { # Напечатаем комбинации }
print(combinations)
#[[], ['a'], ['b'], ['c'], ['a', 'b'], ['a', 'c'], ['b', 'c'], ['a', 'b', 'c']]
Поиск пересечения/объединения двух списков
list(set(list1) & set(list2)) # intersection { # пересечение }
list(set(list1) | set(list2)) # union { # объединение }
Проверка, является ли список подмножеством/надмножеством другого списка
set(list1).issubset(set(list2))
set(list1).issuperset(set(list2))
Различия и сходства двух списков
#Find the difference between two lists: { # Найдем различия двух списков }
list(set(list1) - set(list2))
#Check if two lists have at least one element in common: { # Проверим, есть ли хотя бы один общий элемент у двух списков }
bool(set(list1) & set(list2))
Подсчет количества вхождений каждого слова в строку
import collections; collections.Counter(string.split())
import collections
# Define a sentence { # Определим предложение }
my_sentence = "Python is a powerful programming language. Python is easy to learn and use."
# Count the occurrences of each word in the sentence { # Подсчитаем количество вхождений каждого слова в предложение }
word_counts = collections.Counter(my_sentence.split())
# Print the word counts { # Напечатаем количество слов }
print(word_counts)
#Counter({'Python': 2, 'is': 2, 'a': 1, 'powerful': 1, 'programming': 1, 'language.': 1, 'easy': 1, 'to': 1, 'learn': 1, 'and': 1, 'use.': 1})
Поиск самого часто встречающегося слова в строке
import collections; collections.Counter(string.split()).most_common(1)[0][0]
import collections
# Define a sentence { # Определим предложение }
my_sentence = "Python is a powerful programming language. Python is easy to learn and use."
# Find the most common word in the sentence { # Найдем самое часто встречающееся слова в предложение }
most_common_word = collections.Counter(my_sentence.split()).most_common(1)[0][0]
# Print the most common word { # Напечатаем самое часто встречающееся слово }
print("The most common word is:", most_common_word)
#The most common word is: Python { # Самое часто встречающееся слово: Python }
Генерация случайного пароля
import random, string; ''.join(random.choices(string.ascii_letters + string.digits + string.punctuation, k=n))
import random
import string
# Define the length of the random string { # Определим длину случайной строки }
n = 10
# Generate a random string of length n { # Сгенерируем случайную строку длиной n }
random_string = ''.join(random.choices(string.ascii_letters + string.digits + string.punctuation, k=n))
# Print the random string { # Напечатаем случайную строку }
print("Random string:", random_string)
#Random string: vJ76*,T<~j { # Случайная строка: vJ76*,T<~j }
Преобразование строки в объект DateTime
import datetime; datetime.datetime.strptime(string, format_string)
#Convert a datetime object to a string: { # Преобразуем объект типа DateTime в строку }
datetime_object.strftime(format_string)
#Calculate the difference between two datetime objects: { # Вычислим разность двух объектов типа DateTime }
datetime2 - datetime1
#Get the current date and time: { # Получим текущие дату и время }
import datetime; datetime.datetime.now()
#Get the day of the week for a given date: { # Получим день недели для заданной даты }
datetime_object.strftime('%A')
#Get the month name for a given date: { # Получим названием месяца для заданной даты }
datetime_object.strftime('%B')
import datetime
# Define a string representing a date and time { # Определим строку, представляющую дату и время }
date_string = '2023-07-01 09:30:00'
# Define the format string for the date and time { # Определим формат строки для даты и времени }
format_string = '%Y-%m-%d %H:%M:%S'
# Parse the date and time string { # Разберем строку даты и времени }
parsed_date = datetime.datetime.strptime(date_string, format_string)
# Print the parsed date and time { # Напечатаем разобранные дату и время }
print("Parsed date:", parsed_date)
# Parsed date: 2023-07-01 09:30:00 { # Разобранные дата и время: 2023-07-01 09:30:00 }
Поиск индекса первого вхождения элемента в список с помощью бинарного поиска
import bisect; bisect.bisect_left(list, element)
import bisect
# Define a sorted list of numbers { # Определим отсортированный список чисео }
my_list = [1, 3, 4, 7, 9]
# Define an element to insert into the list { # Определим элемент, входящего в список }
my_element = 5
# Find the insertion point of the element in the list { # Ищем точку вхождения элемента в список }
insertion_point = bisect.bisect_left(my_list, my_element)
# Print the insertion point { # Печатаем точку вхождения }
print("Insertion point:", insertion_point)
#Insertion point: 2 { # Точка вхождения: 2 }
#Find the index of the last occurrence of an element in a list using binary search: { # Находим индекс последнего вхождения элемента в список с помощью бинарного поиска }
import bisect; bisect.bisect_right(list, element) - 1
Подсчет количества вхождений каждого элемента в список и сохранение результата в словаре
import collections; collections.Counter(list)
import collections
# Define a list of elements { # Определяем список элементов }
my_list = ['apple', 'banana', 'orange', 'apple', 'banana', 'banana']
# Count the occurrences of each element in the list { # Подсчитываем количество вхождений каждого элемента в список }
element_counts = collections.Counter(my_list)
# Print the element counts { # Печатаем количество элементов }
print(element_counts)
#Counter({'banana': 3, 'apple': 2, 'orange': 1})
Поиск моды/медианы списка
import statistics; statistics.mode(list)
import statistics; statistics.median(list)
Проверка, является ли строка панграммой (то есть содержит все буквы алфавита)
set('abcdefghijklmnopqrstuvwxyz').issubset(set(string.lower()))
Удаление всех неалфавитных символов из строки
import re; re.sub('[^0-9a-zA-Z]+', '', string)
import re
# Define a string with non-alphanumeric characters { # Определяем строку, в которой есть неалфавитные символы }
my_string = "This is an example string with spaces, punctuation marks, and digits (like 123)."
# Remove all non-alphanumeric characters from the string { # Удаляем все неалфавитные символы из строки }
clean_string = re.sub('[^0-9a-zA-Z]+', '', my_string)
# Print the clean string { # Печатаем «очищенную» строку }
print(clean_string)
#Thisisanexamplestringwithspacespunctuationmarksanddigitslike123
Разворот списка на месте
list.reverse()
Вычисление векторного произведения двух векторов
import numpy; numpy.cross(vector1, vector2)
Получения имя хост-системы текущего компьютера
import socket; socket.gethostname()
Проверка доступности порта на удаленном компьютере
import socket; sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM); result = sock.connect_ex((ip_address, port)); sock.close(); result == 0
Получение IP-адреса текущего компьютера
import socket; socket.gethostbyname(socket.gethostname())
Проверка, является ли строка приемлемым адресом электронной почты
import re; bool(re.match(r'^[\w\.\+\-]+\@[\w]+\.[a-z]{2,3}$', email))
Создание zip-файла
import zipfile; with zipfile.ZipFile('filename.zip', 'w', zipfile.ZIP_DEFLATED) as zip: zip.write('filename.txt')
Извлечение данных из zip-файла
import zipfile; with zipfile.ZipFile('filename.zip', 'r') as zip: zip.extractall('dirname')
Проверка наличия установленного модуля
import importlib; importlib.util.find_spec('modulename') is not None
Получение переменных окружения
import os; os.environ
Выполнение команды оболочки
import os; os.system('command')
Получение текущей версии Python
import platform; platform.python_version()
Получение имени текущего пользователя
import getpass; getpass.getuser()
Копирование файла
import shutil; shutil.copy('sourcefile', 'destinationdir')
Подсчет количества слов в файле
import re; len(re.findall(r'\w+', open('filename.txt').read()))
Переименование файла
import os; os.rename('oldname', 'newname')
Удаление каталога и всего его содержимого
import shutil; shutil.rmtree('dirname')
Получение текущего рабочего каталога
import os; os.getcwd()
Создание каталога
import os; os.mkdir('dirname')
Проверка существования файла
import os; os.path.exists('filename.txt')
# Get the size of a file in bytes: { # Получаем размер файла в битах }
import os; os.path.getsize('filename.txt')
# Get the last modified time of a file: { # Получаем время последнего изменения файла }
import os; os.path.getmtime('filename.txt')
# Delete a file: { # Удаляем файл }
import os; os.remove('filename.txt')
Переход в спящий режим на заданное количество секунд
import time; time.sleep(seconds)
Генерация случайного целого числа между a и b
import random; random.randint(a, b)
Проверка, находится ли число в диапазоне
in_range = lower_bound <= value <= upper_bound
Проверяет, находится ли значение «value» в диапазоне между «lower_bound» и «upper_bound»
Проверка, начинается ли строка с определенной подстроки
starts_with = s.startswith(substring)
Проверяет, начинается ли строка «s» с подстроки «substring»
ends_with = s.endswith(substring)
Проверяет, заканчивается ли строка «s» подстрокой «substring»
Вычисление евклидового пространства между двумя точками
distance = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
Вычисляет евклидово пространство между точками (x
1
, y
1
) и (x
2
, y
2
)
import math
# Define two points in two-dimensional space { # Определяем две точки в двумерном пространстве }
x1, y1 = 2, 3
x2, y2 = 5, 7
# Calculate the Euclidean distance between the two points { # Вычисляем эвклидово пространство между двумя точками }
distance = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
print(f"The distance between ({x1}, {y1}) and ({x2}, {y2}) is {distance:.2f}.")
#The distance between (2, 3) and (5, 7) is 4.24. { # Расстояние между точками (2, 3) и (5, 7) – 4.24. }
Заключение
Я надеюсь, что эта статья была для вас познавательной и интересной. В Python есть огромное количество мощных однострочников, и то, что я продемонстрировал здесь, - лишь верхушка айсберга.
Фаервол на Микротике основан на базе принципов iptables в Linux позволяет фильтровать входящий и исходящий трафик по определенным правилам. В статье мы хотим рассказать про ключевые компоненты Firewall, дизайне и реализации этого инструмента. Погнали!
Общее представление
Основная идея любого фаервола это определение того, что разрешено и запрет всего остального. Так работают все современные инструменты фильтрации. При наличии фаервола, сеть можно разделить на ненадежные, полу - надежные и надежные.
Firewall Chains
Цепочки (последовательности) фаерволов сопоставляют по своим правилам входящий и исходящий с интерфейса трафик. После того, как трафик попал под определенное правило («сматчился»), вы можете совершать определенные манипуляции с ним: разрешить, блокировать, отклонить, внести в лог запись и так далее. В Mikrotik есть следующие флаги: Input, Output и Forward.
Input Chain
Input матчит входящий на интерфейсы маршрутизатора трафик. Условно говоря – это прилетающие на роутера IP - пакеты. Обычная практика – дропать пакеты, прилетающие на WAN, направленные на сканирование портов, попытки взлома и прочие. Помимо этого, многие блокируют входящий трафик изнутри локальной сети (например, допуск к Winbox или SSH должен быть только с определенного VLAN – остальные дропаются).
Всегда используйте VLAN – это базовое разграничение, которое позволит вам обеспечить современные стандарты безопасности.
Output Chain
Как можно догадаться по названию, данный инструмент направлен на фильтрацию исходящего от роутера трафика. Здесь можно блокировать запросы, исходящие непосредственно с роутера: например, DNS или ICMP запрос с роутера.
Forward Chain
Самое интересное – данный инструмент «матчит» трафик проходящий через Mikrotik с одного интерфейса на другой. Пример: пакет, отправленный с хоста внутри LAN через маршрутизатор в сторону провайдера. Пакет прилетает на внутренний интерфейс, а выходит через WAN.
Firewall Actions
Правила на фаерволе могут делать множество вещей, основные из которых: accept (принять), drop (сбросить) и отклонить (reject).
Accept
Данное правило позволяет просто «пропустить» проходящий через фаервол трафик. Никакой модификации или изменения маршрута – пакету будет позволено продолжить свой изначальный путь.
Reject
Фаервол может легко отклонить (сделать reject) пакетов, которые попадут под определенное правило. При этом, источнику такого пакета будет отправлено уведомление о соответствующей блокировке.
В данном методе есть один весомый минус: в случае, если злоумышленник попробует «сканировать» порты или совершить другой вид атаки – отправленные в его сторону REJECT сообщения лишь помогут ему в злодеяниях. Поэтому, в целях безопасности, мы рекомендуем использовать DROP.
Drop
Данное правило «дропает» пакет без отправления уведомления об этом источнику. Этот метод наиболее безопасен на этапе защиты своего Mikrotik от сканирования портов и прочих атак.
Firewall Rules
Правила Firewall определяют пакеты, которые будут обработаны на уровне фаервола, а какие будут отброшены. Каждое правило – это комбинация параметров IP – адресации (источник/получатель пакета), цепочек (chains), действий (actions), интерфейсов и прочих опций. Как мы говорили ранее – хорошо настроенный фаервол пропустит только необходимый для бизнеса трафика, дав запрет на пропуск всего остального потока трафика. Указывая набор разрешающих правил, всегда замыкайте их на конце строчкой «DENY ALL» (запретить все).
Chains
Каждое создаваемое правило назначается определенной цепочке (chain). После определения принадлежности к цепочке, пакеты проходят проверку через последовательность правил в порядке убывания (сверху вниз).
Порядок правил в фаерволе играет важную роль! Поэтому, от последовательности проверки зависит эффективность фильтрации.
Actions
Правило отрабатывает по одному из основных действий: принять (accept), отклонить (reject) и отбросить (drop). Выше мы подробнее рассказывали про каждое из указанных действий.
Адресация
Нашему правилу можно сказать, по какому критерию проводить блокировку: это может быть протокол, IP – адрес (это может быть как хост с /32 маской, так и целая подсеть с /24, например). Помимо этого, критерием могут быть физические или логические интерфейсы (eth/GRE).
Комментарии
Создавая правила комментируйте их. Это важно, как и при программировании – код без комментариев очень сложно анализировать и понимать в будущем.
Советы
Хотим так же поделиться парой полезных советов по настройке Firewall:
Разрешайте только необходимый для работы трафик - да, это сложно. Но методом проб и ошибок мы рекомендуем добиться той настройки фаервола, в рамках которой все ваши подключения будут ясны и понятны.
Подключения только с определенного пула адресов - это может быть удаленный офис, IP – адреса ЦОД или VPN адресация. Тут нужно быть особенно бдительным.
В конце правил всегда используйте «deny all» - после того, как вы выполнили первую и вторую рекомендации и весь тип трафика по протоколам, адресации, источникам (в том числе L7, например) четко определен – в конце цепочки добавьте правило запрета всего. Это будет означать, дословно: «Все, что не разрешено - запрещено».
Атакуйте свою сеть! - да, да, вы не ослышались. Конечно, без фанатизма :) Мы предлагаем периодически сканировать порты на вашем фаерволе. Например, это можно делать с помощью утилиты исследования сети Nmap.
Это продолжение статьи про пакетную коммутацию. Первая часть тут.
Схемы агрегации каналов берут несколько физических каналов и объединяют их в один виртуальный канал. В целях протоколов маршрутизации и алгоритмов предотвращения петель, таких как связующее дерево, виртуальный канал обрабатывается, как если бы он был одним физическим каналом.
Агрегирование каналов используется для увеличения пропускной способности между узлами сети без необходимости замены более медленных физических каналов на более быстрые. Например, два канала 10 Гбит/с можно объединить в один канал 20 Гбит/с, тем самым удвоив потенциальную полосу пропускания между двумя узлами, как показано на рисунке 6. Слово «потенциал» было выбрано тщательно, поскольку агрегированные каналы на практике не масштабируются линейно.
Проблема, с которой сталкивается агрегация каналов, заключается в определении, какие пакеты должны быть отправлены по какому элементу связи. Интуитивно это может показаться не проблемой. В конце концов, казалось бы, имеет смысл использовать группу каналов связи в циклическом режиме. Первоначальный фрейм будет отправлен по первому элементу связки, второй фрейм - по второму элементу и так далее, в конечном итоге возвращаясь к первому элементу связки. Таким образом, канал должен использоваться идеально равномерно, а пропускная способность - линейно.
В реальной жизни существует очень мало подобных реализаций, в которых агрегированные каналы используются на такой циклической основе, как эта, потому что они рискуют доставить неупорядоченные пакеты. Предположим, что первый кадр Ethernet отправляется первому звену нисходящего канала, а второй кадр - второму элементу нисходящего канала сразу после него. По какой-то причине второй кадр попадает на другой конец раньше первого кадра. Пакеты, содержащиеся в этих кадрах, будут доставлены принимающим узлам в неупорядоченном порядке - пакет два перед пакетом один. Это проблема, потому что теперь на хост возлагается вычислительная нагрузка по переупорядочению пакетов, чтобы можно было правильно собрать всю дейтаграмму.
Поэтому большинство поставщиков реализуют хеширование потоков, чтобы гарантировать, что весь поток трафика использует один и тот же элемент пакета. Таким образом, нет никакого риска того, что хост получит пакеты не по порядку, так как они будут отправляться последовательно через один и тот же элемент канала.
Хеширование потока работает путем выполнения математической операции над двумя или более статическими компонентами потока, такими как MAC-адреса источника и получателя, IP-адреса источника и получателя, протокол управления передачей (TCP) или протокол дейтаграмм пользователя (UDP). номера портов для вычисления элемента связи, который будет использовать поток. Поскольку характеристики потока статичны, алгоритм хеширования приводит к идентичным вычислениям для каждого кадра или пакета в потоке трафика, гарантируя, что один и тот же канал будет использоваться в течение всего срока службы потока.
Хотя хеширование потока решает проблему неупорядоченных пакетов, оно создает новую проблему. Не все потоки имеют одинаковый размер. Некоторые потоки используют большую полосу пропускания, например те, которые используются для передачи файлов, резервного копирования или хранения. Их иногда называют «слоновьими потоками» (elephant flows). Другие потоки довольно малы, например, те, которые используются для загрузки веб-страницы или связи с использованием передачи голоса по IP. Их иногда называют «мышиными потоками» (mouse flows). Поскольку потоки имеют разные размеры, некоторые элементы связи могут работать на полную мощность, а другие - недостаточно.
Это несоответствие в использовании возвращает нас к вопросу о линейном масштабировании. Если бы фреймы были сбалансированы по нагрузке через агрегированный набор каналов совершенно равномерно, то добавление новых каналов в набор равномерно увеличило бы емкость. Однако алгоритмы хэширования в сочетании с непредсказуемым объемом потоков трафика означают, что связанные каналы не будут загружаться равномерно.
Задача сетевого администратора - понять тип трафика, проходящего через агрегированный канал, и выбрать доступный алгоритм хеширования, который приведет к наиболее равномерному распределению нагрузки. Например, некоторые соображения по этому поводу:
Обмениваются ли многие хосты в одном широковещательном домене друг с другом через агрегированный канал? Хеширование против MAC-адресов, найденных в заголовке кадра Ethernet, является возможным решением, потому что MAC-адреса будут разными.
Обменивается ли небольшое количество хостов с одним сервером через агрегированный канал? В этом сценарии может не хватить разнообразия MAC-адресов или IP-адресов. Вместо этого хеширование по номерам портов TCP или UDP может привести к наибольшему разнообразию и последующему распределению трафика по агрегированным ссылкам.
Протокол управления агрегацией каналов (LACP)
При объединении каналов связи необходимо учитывать сетевые устройства на обоих концах канала связи и проявлять особую осторожность, чтобы обеспечить формирование пакета каналов связи при сохранении топологии без петель. Наиболее распространенным способом решения этой проблемы является использование отраслевого стандарта Link Aggregation Control Protocol (LACP), кодифицированного как стандарт 802.3 ad института инженеров электротехники и электроники (IEEE).
На каналах, обозначенных сетевым администратором, LACP объявляет о своем намерении сформировать агрегированный канал с другой стороной. Другая сторона, также выполняющая LACP, принимает это объявление, если объявленные параметры действительны, и формирует канал. Как только группа каналов сформирована, агрегированный канал переводится в состояние пересылки. Затем операторы сети могут запросить LACP для получения информации о состоянии агрегированного канала и о состоянии его членов.
LACP также знает, когда элемент связки выходит из строя, так как управляющие пакеты больше не проходят через сбойный канал. Эта возможность полезна, так как позволяет процессу LACP уведомлять сетевую операционную систему о необходимости пересчета хэшей потока. Без LACP сетевой операционной системе может потребоваться больше времени, чтобы узнать о сбойном канале, что приведет к хешированию трафика к элементу связи, который больше не является допустимым путем.
Существуют и другие протоколы управления агрегацией каналов. В некоторых случаях также возможно создавать пакеты каналов вручную без защиты управляющего протокола. Однако LACP доминирует в качестве стандарта, используемого сетевыми поставщиками, а также ведущими операционными системами и поставщиками гипервизоров для агрегации каналов.
Multichassis Link Aggregation
Multichassis Link Aggregation (MLAG) - это функция, предлагаемая некоторыми сетевыми поставщиками, позволяющая одному агрегированной связке каналов охватывать два или более сетевых коммутатора. Чтобы облегчить это, специальный протокол управления поставщика будет работать между коммутаторами-членами MLAG, заставляя несколько сетевых коммутаторов действовать так, как если бы они были одним коммутатором, в отношении LACP, протокола связующего дерева (STP) и любых других протоколов.
Обычным обоснованием для MLAG является физическая избыточность, когда сетевому инженеру требуется более низкий уровень (например, Ethernet) смежности между сетевыми устройствами (вместо маршрутизируемого соединения), а также требуется, чтобы связка каналов оставалась включенной, если удаленная сторона канала выходит из строя. Распространение связки каналов между двумя или более коммутаторами позволяет выполнить это требование. Рисунок 7 демонстрирует это.
В то время как многие сети используют некоторые разновидности MLAG в производстве, другие уклоняются от этой технологии, по крайней мере частично, потому что MLAG является собственностью. Нет такой вещи, как multivendor MLAG. Тенденции к лучшему проектированию сети в сторону от широко рассредоточенных коммутируемых доменов, сценарий, который выигрывает у MLAG. Вместо этого при проектировании сети наблюдается тенденция к ограниченным коммутируемым доменам, взаимосвязанным посредством маршрутизации, что устраняет необходимость в технологиях MLAG.
Маршрутизированные параллельные каналы
Маршрутизируемые плоскости управления, называемые протоколами маршрутизации, иногда вычисляют набор нескольких путей через сеть с равными затратами. В случае маршрутизации несколько каналов с одинаковой стоимостью могут даже не подключать одну пару устройств; Рисунок 8 демонстрирует это.
На рисунке 8 есть три пути:
[A, B, D] общей стоимостью 10
[A, D] общей стоимостью 10
[A, C, D] общей стоимостью 10
Поскольку эти три пути имеют одинаковую стоимость, все они могут быть установлены в локальной таблице переадресации в точках A и D. Маршрутизатор A, например, может пересылать трафик по любому из этих трех каналов в направлении D. Когда маршрутизатор имеет несколько вариантов. чтобы добраться до того же пункта назначения, как он решает, какой физический путь выбрать?
Как и в случае с ECMP нижнего уровня, ответ - хеширование. Маршрутизированное хеширование ECMP может выполняться в различных областях. Общие поля для хеширования включают IP-адреса источника или назначения и номера портов источника или назначения. В результате хеширования выбирается согласованный путь на протяжении потока L3. Только в случае сбоя канала потребуется перестроить поток и выбрать новый канал пересылки.
Механизмы обработки пакетов
Шаги, связанные с маршрутизацией одного пакета, могут показаться очень простыми—найдите пункт назначения в таблице, создайте (или извлеките) перезапись заголовка MAC, перепишите заголовок MAC, а затем поместите пакет в правильную очередь для исходящего интерфейса. Как бы просто это ни было, все равно требуется время, чтобы обработать один пакет. На рисунке 9 показаны три различных пути, по которым пакет может быть коммутироваться в сетевом устройстве.
Рисунок 9 иллюстрирует три различных пути коммутации через устройство; это не единственные возможные пути коммутации, но они являются наиболее распространенными. Первый путь обрабатывает пакеты через программное приложение, работающее на универсальном процессоре (GPP), и состоит из трех этапов:
Пакет копируется с физического носителя в основную память
Физический сигнальный процессор, чип PHY, посылает сигнал на GPP (вероятно, но не обязательно, главный процессор в сетевом устройстве), называемый прерыванием.
Прерывание заставляет процессор останавливать другие задачи (вот почему это называется прерыванием) и запускать небольшой фрагмент кода, который будет планировать запуск другого процесса, приложения коммутации, для выполнения позже.
Когда приложение коммутации запустится, оно выполнит соответствующий поиск и внесет соответствующие изменения в пакет.
После коммутации пакета он копируется из основной памяти исходящим процессором. Такое переключение пакета через процесс часто называется коммутацией процесса (по понятным причинам) или иногда медленным путем. Независимо от того, насколько быстрым является GPP, для достижения полной линейной скорости коммутации на высокоскоростных интерфейсах требуется большая настройка - до такой степени, что это практически невозможно. Второй путь коммутации, показанный на рисунке 9, был разработан для более быстрой обработки пакетов:
Пакет копируется с физического носителя в основную память
Микросхема PHY прерывает GPP; код обработчика прерывания, а не вызов другого процесса, фактически обрабатывает пакет.
После коммутации пакета, пакет копируется из основной памяти в процесс вывода, как описано ниже. По понятным причинам этот процесс часто называют interrupt context switching; многие процессоры могут поддерживать коммутацию пакетов достаточно быстро, чтобы передавать пакеты между интерфейсами с низкой и средней скоростью в этом режиме. Сам код коммутации, конечно же, должен быть сильно оптимизирован, потому что коммутация пакета заставляет процессор прекращать выполнение любых других задач (например, обработки обновления протокола маршрутизации). Первоначально это называлось - и до сих пор иногда называется fast switching path. Для действительно высокоскоростных приложений процесс коммутации пакетов должен быть выгружен с главного процессора или любого типа GPP на специализированный процессор, предназначенный для конкретной задачи обработки пакетов. Иногда эти процессоры называются сетевыми процессорами (Network Processing Units -NPU), подобно тому, как процессор, предназначенный для обработки только графики, называется графическим процессором (Graphics Processing Unit-GPU). Эти специализированные процессоры являются подмножеством более широкого класса процессоров, называемых специализированными интегральными схемами (Application-Specific Integrated Circuits -ASIC), и инженеры часто просто называют их ASIC. Переключение пакета через ASIC показано как шаги с 7 по 9 на рисунке 9:
Пакет копируется с физического носителя в память ASIC
Микросхема PHY прерывает работу ASIC; ASIC обрабатывает прерывание путем переключения пакета.
После коммутации пакета пакет копируется из памяти ASIC в процесс вывода, как описано ниже.
Многие специализированные ASIC для обработки пакетов имеют ряд интересных функций, в том числе:
Структуры внутренней памяти (регистры) настроены специально для обработки различных типов адресов, используемых в сетях.
Специализированные наборы команд, предназначенные для выполнения различных требований к обработке пакетов, таких как проверка внутренних заголовков, переносимых в пакете, и перезапись заголовка MAC.
Специализированные структуры памяти и наборы инструкций, предназначенные для хранения и поиска адресов назначения для ускорения обработки пакетов
Возможность повторного использования пакета через конвейер пакетов для выполнения операций, которые не могут поддерживаться за один проход, таких как глубокая проверка пакетов или специализированные задачи фильтрации.
