Part_B

Примечание

Задание 1

Назвать минимум 3 отличия в коде: print(..., file=f) и f.write(...)

Ответ:
1) print преобразует объекты в строку автоматически, f.write требует именно строку
2) print добавляет символ новой строки в конце
3) print может выводить несколько объектов через запятую с разделителем, f.write принимает только одну строку

Задание 2

Расскажите, как вычисляется выражение a or b

Ответ:
Возвращает первое истинное значение из двух операндов или последнее (b), если оба ложны. Сначала вычисляется a; если a истинно, результат — a, иначе результат — b.

Задание 3

Дано вещественное число x. Как его преобразовать в строку с точностью до 4-х знаков после запятой?

Ответ:
s = f"{x:.4f}"

Задание 4

Назовите минимум 3 потенциальные проблемы приведённого декоратора.

def log_calls(func):
    def _wrap(x):
        print(x)
        func(x)
    return _wrap

Ответ:
1) не сохраняет метаданные исходной функции
2) ограничивает количество аргументов
3) игнорирует возвращаемое значение

Задание 5

Что напечатает код и почему?

class A:
    X = 1
(a, b) = (A(), A())
(b.X, A.X) = (2, 3)
print(a.X, b.X, A.X)

Ответ:
3 2 3
По умолчанию A() использует X=1
Дальше b.X создает атрибут экземпляра и теперь X это его собственное свойство
Дальше A.X меняет X для всех экземпляров которые не переопределили этот атрибут

Задание 6

В чём отличие и как используются методы __add__, __iadd__, __radd__?

Ответ:
__add__ создает новый объект и вызывается для a+b (a+b)
__iadd__ изменяет a и вызывается только когда += (a+=b)
__radd__ создает новый объект и вызывается когда b.__add__(a) не сработал (b+a)

Задание 7

Что такое и как используется атрибут __mro__ у класса?

Ответ:
__mro__ (Method Resolution Order) — это кортеж, хранящий порядок, в котором Python ищет методы и атрибуты для данного класса, когда происходит множественное наследование. Он используется для определения, в каком порядке будут вызываться методы классов-предков при вызове super().

Задание 8

Как открыть файл 1.dat на запись в кодировке cp866?

Ответ:
f = open(' 1.dat', 'w', encoding='cp866')
или with open(' 1.dat', 'w', encoding='cp866') as f:

Задание 9

Назовите и кратко поясните назначение параметров функции open (минимум 4).

Ответ:
file - нужно указать название файла в текущей директории
mode - необязательный, режим работы с файлом, по-умолчанию r (на чтение)
encoding - необязательный, кодировка, по умолчанию None
newline - необязательный, управление конвертацией перевода строк, по-умолчанию None
buffering - размер буфера (целое число). Регулирует производительность ввода/вывода.
errors - обработка ошибок кодировки (строка), например ignore, replace

Задание 10

Какие задачи решают с помощью регулярных выражений?

Ответ:
- поиск
- сопоставление
- извлечение
- замена паттернов

Задание 11

Какие имеются проблемы при сортировке строк?

Ответ:
- Различия регистра
- Языковая специфика
- Числа сортируются лексикографически, а не численно
- Пробелы и спецсимволы влияют на порядок

Задание 12

Дан кортеж t. Как его «развернуть» (задом наперёд)?

Ответ:
reversed_t = t[::-1]

Задание 13

Как, согласно PEP8, нужно именовать функции?

Ответ:
C маленькой буквы с разделением слов нижним подчеркиванием _ (snake_case)

Задание 14

Назовите минимум 5 методов, которые есть у match object.

Ответ:
- group() – получить найденную строку/группы.
- groups() – получить кортеж всех захваченных групп.
- start() – позиция начала совпадения или группы.
- end() – позиция конца совпадения или группы.
- span() – кортеж (start, end) для совпадения или группы.

Задание 15

Дан объект o. Напишите подробно, как работает dir(o) в зависимости от типа объекта o.

Ответ:
dir(o) возвращает список имен атрибутов и методов объекта o.
- Если o — экземпляр класса, он включает атрибуты экземпляра, а также атрибуты и методы, унаследованные от класса и всех его базовых классов (через __dir__ или непосредственно).
- Если o — класс, он включает атрибуты и методы самого класса, а также унаследованные от его базовых классов.
- Если o — модуль, dir(o) возвращает список имен, определённых в пространстве имён модуля.
- Если без аргументов (dir()), возвращает список имен в текущей области видимости.
- В конечном итоге, dir() вызывает метод __dir__() объекта, если он существует.

Задание 16

Дан объект o и строка s. Как проверить, что объект содержит атрибут с данным названием?

Ответ:
hasattr(o, s) - вернет True, если есть атрибут с именем s

Задание 17

Что такое декоратор? Приведите минимально возможный пример декоратора.

Ответ:
Декоратор - это функция, которая принимающая на вход функцию и расширяет её функциональность не изменяя её код явно.

def d(f):
    return f

Задание 18

Дан список xs. Приведите как можно больше способов сделать его поверхностную копию.

Ответ:
- xs.copy()
- list(xs)
- xs[:]
- [x for x in xs]
- copy.copy(xs)

Задание 19

Что нужно написать вместо XXX, чтобы вывести [89, 34, 13, 5, 2]?

xs = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
print(xs[XXX])

Ответ:
10:1:-2

Задание 20

Какой декоратор может быть полезен при создании своих декораторов? Что он делает?

Ответ:
@functools.wraps, он сохраняет метаданные исходной функции - название, документацию и т.д.

Задание 21

Приведите три способа проверить содержится ли подстрока a в строке b.

Ответ:
- a in b
- b.find(a) != -1
- b.count(a) > 0

Задание 22

Назовите минимум 3 отличия списка от множества (как структуры данных).

Ответ:
1) списки могут содержать дубликаты, а множества нет
2) в списках сохраняется порядок элементов, а в множестве нет
3) множество может содержать только хэшируемые типы
4) Множество проверяет наличие в лучшем случае за O(1), список - O(n)

Задание 23

Можно ли к функции применить несколько декораторов? Если да, приведите пример и кратко поясните, в каком порядке они применяются.

Ответ:
да, применяется снизу вверх

def decor_first(func):
    def wrapper(*args, **kwargs):
        print(1)
        return func(*args, **kwargs)
    return wrapper

def decor_second(func):
    def wrapper(*args, **kwargs):
        print(2)
        return func(*args, **kwargs)
    return wrapper

@decor_second
@decor_first
def foo():
    pass

@decor_first
@decor_second
def bar():
    pass

Задание 24

Назовите минимум 3 атрибута, не являющиеся методами, которые содержит класс A:

class A:
    pass

Ответ:
- __name__
- __module__
- __dict__
- __class__
- __doc__

Задание 25

Напишите регулярное выражение, под которое бы попадали подстроки в одинарных кавычках.

Ответ:
r"'[^']*'"

Задание 26

Файл 1.txt существует, имеет достаточный размер и корректные права на чтение. Какая проблема может возникнуть в участке кода ...?

with open('
1.txt') as f:
    f.seek(100)
    ...

Ответ:
f.seek(100) может попасть в середину символа если он занимает несколько байт

Задание 27

Как получить количество ссылок на объект o?

Ответ:
sys.getrefcount(o) - 1
минус 1 из-за временной ссылки созданной при вызове функции

Задание 28

Как вывести строку s на стандартный поток ошибок?

Ответ:
print(s, file=sys.stderr)

Задание 29

Дана байтовая строка s. Как её преобразовать в строку в кодировке UTF8, проигнорировав невалидные байты?

Ответ:
s.decode('utf-8', errors='ignore')

Задание 30

Перечислить минимум 5 ошибок, которые могут произойти при выполнении кода:

with open('file.txt', 'r') as f:
    data = f.read()

Ответ:
- FileNotFoundError- файл не существует
- PermissionError- нет прав на чтение файла
- IsADirectoryError - путь указывает на директорию, а не на файл
- UnicodeDecodeError - файл содержит байты, несовместимые с используемой кодировкой
- MemoryError - недостаточно памяти для чтения очень большого файла целиком
- IOError - сбой ввода-вывода (например, проблема с ОС/диском)
- ValueError - файл был закрыт раньше, чем вызван .read()
- BlockingIOError - файл не готов к чтению (например, при работе с неблокирующим устройством)
- TypeError - неверный тип аргумента в open (например, нестроковый путь)

Задание 31

Напишите такой класс A, что вызов A()(x) вернёт x + 1.

Ответ:

class A:  
    def __call__(self, x):  
        return x + 1

Задание 32

Расскажите, что происходит, если регулярное выражение в re.split содержит захват.

Ответ:
Группы захвата включаются в результат

Задание 33

Как прочитать со стандартного потока ввода ровно 1 байт?

Ответ:
sys.stdin.buffer.read(1)

Задание 34

Какой метод нужно реализовать в классе, чтобы объект o данного класса можно было использовать так: o()?

Ответ:
__call__

Задание 35

Что нужно написать вместо <x>, чтобы в переменной z хранилось [2, 3]?

<x> = 1, 2, 3, 4
z = <x>[1:3]

Ответ:
x

Задание 36

Какие параметры принимает функция re.sub?

Ответ:
re.sub() в модуле используется для замены совпадений регулярного выражения в строке.

Параметры:
- pattern - регулярное выражение
- repl - строка или функция для замены найденных совпадений
- string - исходная строка, в которой будет производиться замена
- count (опционально) - максимальное количество замен (по умолчанию заменяются все)
- flags (опционально) — дополнительные флаги регулярного выражения, например, re.IGNORECASE

Задание 37

Напишите пример собственного класса, объекты которого нельзя положить в set. Базовым классом должен быть object.

Ответ:

class A(object):
    __hash__ = None

Задание 38

Дана строка s. Как создать строку, в которой первый символ заменён на букву x?

Ответ:
new_s = 'x' + s[1:]

Задание 39

Верно ли, что на момент выполнения строки # 1 в файле будет содержаться строка string? Если нет, что нужно написать вместо # 1, чтобы это случилось?

with open('file', 'w') as f:
    f.write('string')
    # 1
    # some code

Ответ:
Нет, данные могут находиться в буфере файлового объекта и ещё не быть записанными на диск.
f.flush()

Задание 40

Что такое нормализация unicode? Поясните на примере.

Ответ:
это процесс приведения разных вариантов записи одних и тех же символов или сочетаний символов к стандартной (однозначной) форме.
Пример:

# Без нормализации
'café' == 'café'  # False
# С нормализацией
n1 = unicodedata.normalize('NFC', 'café')
n2 = unicodedata.normalize('NFC', 'café')
print(n1 == n2)  # True

Задание 41

Расскажите, как происходит поиск атрибута x в выражении o.x.

Ответ:
В выражении o.x поиск атрибута x происходит по следующему алгоритму:

  1. Ищется в словаре экземпляра (o.__dict__)

  2. Если не найден, ищется в классе объекта (type(o))

  3. Если не найден, ищется во всех базовых классах по порядку __mro__

  4. Если атрибут не найден, и определён метод __getattr__, вызывается он

  5. Если в классе определён дескриптор (например, property), срабатывают методы дескриптора (__get__, __set__, __delete__)

Задание 42

Приведите пример таких A и B, что A % B < 0

Ответ:

A = 5
B = -3

Задание 43

В каких целях используется метод __repr__? Как его обычно реализуют?

Ответ:
Используется для создания однозначного, однозначно интерпретируемого строкового представления объекта, которое в идеале должно быть валидным кодом Python, позволяющим воссоздать этот объект (или идентичный ему).

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Point(x={self.x}, y={self.y})"

Задание 44

Как в регулярном выражении создать именованную группу для захвата?

Ответ:
(?P<name>...)

Задание 45

Назовите причины, по которым писать type(o) == T зачастую является плохой практикой.

Ответ:

  1. Не учитывает наследование

  2. Труднее модифицировать и поддерживать код

  3. В большинстве случаев предпочтительнее isinstance(o, T)

Задание 46

Является ли приведённый код корректным? Если нет, по почему?

class A:
    def __init__(self):
        self._x = None

    @x.setter
    def set_x(self, val):
        self._x = val

    @property
    def x(self):
        return self._x

Ответ:
Код некорректен: аннотация @x.setter должна идти после объявления @property def x, иначе Python не знает, к чему применять @x.setter. Кроме того, имя метода-сеттера обязательно должно совпадать с именем свойства, то есть быть тоже x

Задание 47

Что такое регулярный язык?

Ответ:
Регулярный язык — это множество строк, формализуемое с помощью регулярного выражения (или конечного автомата)

Задание 48

Дан список xs. Как из него удалить всё?

Ответ:
- xs.clear()
- del xs[:]

Задание 49

Дана строка s. Как создать строку, в которой первое вхождение подстроки u заменено на строку v?

Ответ:
s.replace(u, v, 1)

Задание 50

Как считать последние 36 байт файла 1.dat?

Ответ:

with open('
1.dat', 'rb') as f:
    f.seek(-36, 2)
    data = f.read(36)

Задание 51

Напишите пример функции, принимающей произвольное количество позиционных параметров и только их.

Ответ:

def f(*args):
    pass

Задание 52

Как добавить элемент x в конец списка xs?

Ответ:
xs.append(x)

Задание 53

Дана строка text. Как с помощью регулярных выражений получить список всех выражений, взятых в одинарные кавычки?

Ответ:

import re
matches = re.findall(r"'([^']*)'", text)

Задание 54

Даны две строки: s1 и s2. Как проверить их равенство без учёта регистра?

Ответ:
Для английских и обычных строчных букв: s 1.lower() == s 2.lower()
Для интернациональных случаев: s 1.casefold() == s 2.casefold()

Задание 55

Когда вызывается метод __del__ объекта? Что случится, если в нём произойдёт исключение?

Ответ:
- Метод __del__ вызывается, когда объект уничтожается сборщиком мусора, то есть когда его счетчик ссылок падает до нуля (или объект удаляется циклическим сборщиком мусора).
- Если в __del__ возникает исключение, оно игнорируется, сообщение об ошибке может быть выведено в stderr, а программа продолжает работать.

Задание 56

Какие имеются ограничения на заглядывание назад?

Ответ:
- Длина шаблона должна быть фиксированной
- Нельзя использовать конструкции, в которых Python не может заранее вычислить максимальную длину
- Некоторые движки regex

Задание 57

Даны два множества: a и b. Как получить множество c, являющееся их пересечением?

Ответ:

c = a & b
# или
c = a.intersection(b)

Задание 58

Измените выражение в вызове append так, чтобы код вывел [1, 2, 4, 8].

f = []
for n in range(4):
    f.append(lambda x: x**n)
print([f[i](2) for i in range(4)])

Ответ:
lambda x, power=n: x**power

Задание 59

Что лежит в var если выражения type(var) is float и var is var — истинны, а var == var — ложно

Ответ:
float('nan')

Задание 60

Привести пример такого объекта o, для которого type(o) is not o.__class__.

Ответ:

class A:
    @property
    def __class__(self):
        return int

Задание 61

Чем отличаются вызовы .split() и .split(" ") у строки?

Ответ:
- .split() (без аргументов) - разделяет строку по любому количеству пробельных символов
- .split(" ") - разделяет строку строго по одному символу пробела, и не игнорирует пустые подстроки.

Задание 62

Какая проблема есть в следующем коде?

class Max:
    l = []
    def add(el):
        self.l.append(el)
    def max():
        return self.l.max()

Ответ:

  1. Методы объявлены без параметра self (он необходим для методов экземпляра).

  2. Атрибут l — это атрибут класса, а не экземпляра (все объекты разделяют одну и ту же коллекцию).

  3. Вызов self.l.max() — у списка нет метода max, нужно max(self.l)

Задание 63

Дан список xs. Как из него удалить элементы с 3 по 7?

Ответ:
del xs[2:7]

Задание 64

Что нужно написать вместо ... в выражении print("qqqqqqqqqqqqqqqqqqqqqqing"[...::]), чтобы вывелось ing?

Ответ:
-3

Задание 65

Дан объект f. Как проверить, реализует ли он интерфейс функции, т.е. можно написать f(...)?

Ответ:
callable(f)

Задание 66

Какие методы объекта o и с какими параметрами могут быть вызваны в коде x in o?

Ответ:

  1. o.__contains__(x) - если этот метод определён, он вызывается в первую очередь. Он должен вернуть True или False

  2. o.__iter__() - если __contains__ не определён, Python пытается получить итератор для o. Затем он итерирует по o, сравнивая каждый элемент с x

  3. o.__getitem__(index) - если __contains__ и __iter__ не определены, Python пытается использовать индексацию, начиная с o.__getitem__(0), затем o.__getitem__(1) и так далее, пока не будет найдено совпадение или не возникнет IndexError

Задание 67

Как дописать в конец бинарного файла 1.dat байтовую строку s?

Ответ:

with open('
1.dat', 'ab') as f:
    f.write(s)

Задание 68

Написать класс A, для которого выражение A() == A() всегда истинно.

Ответ:

class A:
    def __eq__(self, other):
        return True

Задание 69

Можно ли сравнивать вещественные числа на равенство с помощью ==? Ответ обосновать.

Ответ:
Возможность есть, но будет неточность с плавающей точкой

Задание 70

Дано множество s и элемент x. Как удалить x из s?

Ответ:
s.discard(x) или s.remove(x)

Задание 71

Какая кодировка используется в выражении s.encode()?

Ответ:
utf-8

Задание 72

Назовите проблемы, возникающие при переворачивании строки так: s[::-1]

Ответ:
Это некорректная обработка символов Unicode, состоящих из нескольких кодовых точек (графем)

Задание 73

Укажите три способа конкатенации строк one и two.

Ответ:

  1. result = one + two

  2. result = f"{one}{two}"

  3. result = "".join([one, two])

Задание 74

Как получить список всех наследников класса A?

Ответ:
A.__subclasses__()

Задание 75

Как положить в переменную вещественное число, равное бесконечности?

Ответ:
float('inf')

Задание 76

Какие символы подходят под регулярное выражение r'.'?

Ответ:
соответствует любому одиночному символу, кроме символа новой строки (\n) по умолчанию.

Задание 77

Назовите 3 принципа дизайна Python (import this).

Ответ:
- Красивое лучше, чем уродливое.
- Явное лучше, чем неявное.
- Простое лучше, чем сложное.

Задание 78

Какие методы объекта x могут быть вызваны при его добавлении в множество?

Ответ:

  1. x.__hash__() — вычисляет хеш объекта для поиска позиции в множестве.

  2. x.__eq__(other) — сравнивает x с другими объектами в множестве на предмет равенства, если обнаружена коллизия хешей.

Задание 79

Сколько байт занимает символ в кодировке UTF8?

Ответ:
В кодировке UTF-8 символ может занимать от 1 до 4 байт.