<jupyter_start><jupyter_text>Примеры плохого кода или раздел ```0xbadc0de```Добро пожаловать в раздел ```0xbadc0de```, где собраны забавные и иногда рабочие примеры кода на Python.Примеры могут быть не совсем рабочие или частично доработаны до рабочего состояния.<jupyter_code># Именовать переменные нужно осмысленно, т.е. что бы по их 
# названию можно было понять для чего она предназначена. 
# Плохой практикой является использование:
# - однобуквенных имен, кроме использования их в исторически 
# сложившихся ситуациях, таких как: i, j, k для индексов, 
# x, y, z для координат и т.д.
# - метапеременных: foo, bar, baz и т.д. Исключеним являются 
# использование в короткий примерах.
# - неинформативных имен: lst, lst2, dct, ...

lst = []
lst2 = []

msg = 'Введите имя или stop для завершения:'
while (name:= input(msg)):
    lst.append(name)
    phone = input('Введите номер телефона:')
    lst2.append(phone)

print(f'{lst = }')
print(f'{lst2 = }')
# Нужно создать список, где сохраняются словари вида 
# {'имя': '...', 'телефоны': [{'описание': '...', 'номер': '...'}, {'описание': '...', 'номер': '...'}, ...]}

# Попробуйте самостоятельно понять в чем проблема нижеприведенного кода.

# Проблемы:
# - неинформативные имена
# - использование range(len(lst2)). В теле цикла нужны 
# элементы двух списков, в этом случае можно использовать 
# либо enumerate, либо zip для итерирования по двум 
# коллекциям одновременно
# - совершенно неправильная работа со словарем. Словарь 
# создается один раз, затем его ключи обновляются через update. 
# Используется глубокое копирование. Здесь нужно создавать 
# словарь внутри цикла с нужными ключами и добавлть его в список.

name_per = 'Bob'
lst = ['315-194-6020', '555-2368', '8-800-555-35-35']
lst2 = ['(1)', '(2)', '(3)']

import copy
dct = {}
lst3 = []
lst4 = []
for i in range(len(lst2)):
    dct.update({'описание': lst2[i], 'номер': lst[i]})
    lst3.append(copy.deepcopy(dct))
lst4.append(
    {'имя': name_per, 'телефоны': lst3},
)

# корректная версия
all_phones = ['315-194-6020', '555-2368', '8-800-555-35-35']
descriptions = ['<NAME>', 'Ghostbusters', 'Advertising']
phone_book = []
phones = []
for description, phone in zip(descriptions, all_phones):
    phones.append({'описание': description, 'номер': phone})

phone_book.append(
    {'имя': name_per, 'телефоны': phones},
)
print(phone_book)
# проверка числа x на принадлежность множеству 
# A = {x | x ≠ 0, x ∈ [2/x, 5]}
# Этот пример не совсем рабочий. Предлагается 
# самостоятельно подумать почему.

# Исходное решение
x = 2
print('x in A:', 2/x <= x!=0 <= 5)

# Этот цикл призван показать неправильность решения
for i in range(-10, 10):
    if i == 0:  # Эта проверка добавлена, чтобы избежать исключения
        print('Что-то пошло не так')
    elif 2/i <= i!=0 <= 5:
        print(i, 'in A')
# проверка числа x на принадлежность множеству 
# A = {x | x ≠ 0, x ∈ [2/x, 5]}
# Этот пример работает не так как было задумано изначально

# Исходное решение
x = 2
print('x in A:', [2/x, 3] and (x >= 2/x) and x <= 5)

# Этот цикл призван показать неправильность решения
for i in range(-5, 6):
    if i == 0:  # Эта проверка добавлена, чтобы избежать исключения
        print('Что-то пошло не так')
    elif [2/x, 3] and (x >= 2/x) and x <= 5:
        print(i, 'in A')
# создать список нечетных чисел из интервала [0, 15]
a = [i for i in range(16) if i%2 is not 0]
print(a)
# проверить число x на четность
x = 4
if (x % 2) in [0]:
    print('Четное')
else:
    print('Нечетное')
# один из способов распаковать кортеж длиной два в две переменные
a = (42, 196)
for i in range(len(a)):
    globals()[f'a{i}'] = a[i]
print(a0, a1)
# еще один способ распаковать кортеж длиной два в две переменные a и b
x = (42, 196)
for i in range(len(x)):
    globals()[chr(ord('a') + i)] = x[i]
print(a, b)
# другой вариант распаковать кортеж длиной два в две переменные a и b
x = (42, 196)
for i in range(len(x)):
    if i == 0:
        a = x[i]
    else:
        b = x[i]
print(a, b)
# сравнение числа с заданными значениями
k = 4
if k == 3:
    print('wait for it...')
elif k == 4:
    print('wait for it...')
elif k == 5:
    print('wait for it...')
elif k != 3 or 4 or 5:
    print('Legendary')
# один из способо выравнивания строки
for i in range(8, 16):
    s = ''
    for base in 'bodx':
        s += ' ' * (10 - len(f'{i:{base}}')) + f'{i:{base}}'
    print(s)

print('-' * 50)
# правильный способ выравнивания строки
for i in range(8, 16):
    for base in 'bodx':
        print(f'{i:>10{base}}', end='\n' if base == 'x' else '')
# реализовать функцию, добавляющую к списку число 42,
# если функция вызвана без аргументов, она должна 
# возвращать список из одного элемента: [42]

# неправильная, но полностью рабочая реализация
def foo(a=[]):
    if a == []:
        a = [42]
    else:
        a.append(42)
    return a

print('(1):', foo())
print('(2):', foo())
print('(3):', foo())
print('(4):', foo([]))
print('(5):', foo([1]))
print('(6):', foo([1, 2]))
# реализовать функцию, добавляющую к списку число 42,
# если функция вызвана без аргументов, она должна 
# возвращать список из одного элемента: [42]

# еще одна попытка реализации
def bar(a=None):
    b = a
    a = []
    if isinstance(b, list):
        b.append(42)
        return b
    else:
        a.append(42)
        return a

print('(1):', bar())
print('(2):', bar())
print('(3):', bar())
print('(4):', bar([]))
print('(5):', bar([1]))
print('(6):', bar([1, 2]))
# Пользователь вводит строку, разделенную пробелами. 
# Необходимо проверить, являются ли все элементы строки 
# числами > 0. Если ввод не удовлетворяет условию, то 
# нужно запросить повторный ввод.

# Этот пример демоснтрирует сразу несколько неправильных 
# подходов. Первый заключается в зацикливании программы с 
# помощью рекурсии. Второй в несовмсем правильной проверке ввода.

# Самостоятельно провертьте ввод на следующих примерах и 
# постарайтесь понять в чем проблема.
# '1 2 3' - корректная работа
# '1 2 q' - что-то идет не так, но работает "почти" правильно
# '1 0 O O 4' - нужно больше ввода!
def foo():
    msg = 'Введите числа, раделенные пробелами'
    input_arr = input(msg).split(' ')
    for i in range(len(input_arr)):
        if not input_arr[i].isdigit():
            print('Введите число')
            foo()
    print('Ввод завершен')

foo()
# Пользователь вводит строку, разделенную пробелами. 
# Необходимо проверить, являются ли все элементы строки 
# числами > 0. Если ввод не удовлетворяет условию, то 
# нужно запросить повторный ввод.

# Здесь проблема заключается непосредственно в проверке ввода.

# Самостоятельно провертьте ввод на следующих примерах:
# '1 2 3' - корректная работа
# '1 2 q' - будте отсторожны
# '1 0 O O 4' - нужно больше ввода!
def foo():
    msg = 'Введите числа, раделенные пробелами'
    input_str = input(msg).split(' ')
    for c in input_str:
        while not c.isdigit():
            print('Введите число')
            input_str = input().split(' ')
    print('Ввод завершен')

foo()
# безумная альфа версия языка программирования РУтон

печать = print

икс, игрек = 6, 4
печать('Вектор:', (икс, игрек))

расстояние = (икс**2 + игрек**2) ** 0.5
печать('Длина вектора', расстояние)
# Пример бесполезного наследования
# Здесь пример классов вроде "namedtuple", но еще более бесполезны.  
# Самостоятельно определите проблемы этого кода.

class Plain:
    coefficient = 1
    hours = 6
    base_price = 130

class ExPlain(Plain):
    coefficient = 1.5
    hours = 3
    base_price = 110


a = Plain()
print(f'{a.coefficient = }, {a.hours = }, {a.base_price = }')
b = ExPlain()
print(f'{b.coefficient = }, {b.hours = }, {b.base_price = }')
# Перебор с индексами
# Здесь требуется проитерироваться по списку и использовать индексацию, начина с 1.

xs = [5, 4, 3, 2]

for num, i in enumerate(range(len(xs)), 1):
    print(num, xs[i])
print('-' * 25)

# корректное решение
for i, item in enumerate(xs):
    print(i + 1, item)
# Выстрел в ногу
# Этот пример демонстрирует отрицательные стороны использования глобальных переменных.
# Задача довольно проста. Имеется список словарей. Необходимо сначала выбрать все элементы 
# с заданным значениям первого ключа, затем для полученного результата повторить процедуру 
# для другого ключа.

# Этот пример сильно упрощен, а также добавлен небольшой кусок кода для предотвращения 
# зацикливания (его не было в исходном решении) без потери исходного смысла. Измененены 
# названия переменных на более простые.

# Попробуйте самостоятельно найти проблему данного кода.

# Добавка для предотвращения зацикливания
class Counting:
    """Счетчик вызова функций.
    Можно использовать как декортатор.
    """
    def __init__(self, func):
        self.count = 0
        self.func = func
    
    def __call__(self, *args, **kwargs):
        self.count += 1
        self.func(*args, **kwargs)


# Будем считать количество вызовов метода append
my_append = Counting(list.append)


# глобальные переменные
my_list = [
    {'a': 'foo', 'b': 1},
    {'a': 'bar', 'b': 1},
    {'a': 'foo', 'b': 3},
    {'a': 'baz', 'b': 4}
]
a = []
b = []
c = []


def quuz(list_, key, value):
    for item in list_:
        if value == item.get(key):
            # для получения исходного смысла:
            my_append(c, item)  # закомментируйте эту строку
            # c.append(item)  # раскомментируйте эту строку
        if my_append.count == 5:  # закомментируйте это условие
            print('Превышение количества вызовов. Зацикливание!')
            break
    return c


# демонстрация работы
print('Состояние списков перед выполнением программы:')
print(f'{my_list is a = }')
print(f'{a is b = }')
print(f'{a is c = }')    
print('-' * 50)

a = quuz(my_list, 'a', 'foo')
print(a)

print('Состояние списков (1):')
print(f'{my_list is a = }')
print(f'{a is b = }')
print(f'{a is c = }')
print('-' * 50)

parametr_analiz = 'b'
b = quuz(a, 'b', 1)
print(b)

print('Состояние списков (2):')
print(f'{my_list is a = }')
print(f'{a is b = }')
print(f'{a is c = }')
print('-' * 50)<jupyter_output>Состояние списков перед выполнением программы:
my_list is a = False
a is b = False
a is c = False
--------------------------------------------------
[{'a': 'foo', 'b': 1}, {'a': 'foo', 'b': 3}]
Состояние списков (1):
my_list is a = False
a is b = False
a is c = True
--------------------------------------------------
Превышение количества вызовов. Зацикливание!
[{'a': 'foo', 'b': 1}, {'a': 'foo', 'b': 3}, {'a': 'foo', 'b': 1}, {'a': 'foo', 'b': 1}, {'a': 'foo', 'b': 1}]
Состояние списков (2):
my_list is a = False
a is b = True
a is c = True
--------------------------------------------------
{'fraction_non_alphanumeric': 0.15939296823451787, 'fraction_numerical': 0.02413045527382411, 'mean_word_length': 3.3077547706049533, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '289235', 'license': 'MIT', 'n_tokens_mistral': 4567, 'n_tokens_neox': 4969, 'n_words': 1260, 'path': 'python_pd/badcode.ipynb', 'repo_name': 'Alexey-smurf/python-bp', 'size': '10612'}