-
1. В чем разница между list и tuple?
Ключевая разница — изменяемость: list изменяемый (mutable), tuple — нет (immutable). Tuple обычно быстрее и используется для неизменяемых последовательностей. Примеры:
my_list = [1, 2, 3]
my_tuple = (1, 2, 3)
# my_list.append(4) # допустимо
# my_tuple[0] = 10 # приведет к ошибке
-
2. Что такое GIL (Global Interpreter Lock)?
GIL — это механизм CPython, который позволяет только одному потоку интерпретировать байткод Python одновременно. Это ограничивает многопоточную производительность при CPU-bound задачах. Для параллелизма используют multiprocessing, async IO или реализации без GIL (например, PyPy — частично, или Jython).
-
3. Как работают генераторы и оператор yield?
Генератор — это функция, которая возвращает итератор и использует yield для поэтапной выдачи значений, экономя память. Пример:
def count_up_to(n):
i = 0
while i < n:
yield i
i += 1
for x in count_up_to(5):
print(x)
-
4. Что такое декоратор и пример простого декоратора?
Декоратор — функция, принимающая другую функцию и возвращающая новую функцию с расширенным поведением. Часто используется для логирования, проверки прав, кеширования.
def timer(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print("Elapsed:", time.time() - start)
return result
return wrapper
@timer
def slow():
import time
time.sleep(0.1)
slow()
-
5. Как поймать исключение и что такое finally?
Блок try/except/else/finally позволяет обработать ошибки. finally выполняется всегда, даже при выходе через return или при возникновении исключения.
try:
x = 1 / 0
except ZeroDivisionError as e:
print('Деление на ноль')
else:
print('Ошибок нет')
finally:
print('Ресурсы освобождены')
-
6. Разница между shallow copy и deep copy?
Shallow copy копирует объект верхнего уровня, но вложенные объекты остаются ссылками на те же объекты. Deep copy рекурсивно копирует всю структуру.
import copy
orig = [[1], [2]]
sh = orig.copy()
dp = copy.deepcopy(orig)
orig[0][0] = 99
print(sh) # [[99], [2]]
print(dp) # [[1], [2]]
-
7. Объясните mutable и immutable объекты и примеры.
Mutable — изменяемые объекты (list, dict, set), immutable — неизменяемые (int, float, str, tuple). Это важно при передаче аргументов в функции: изменение mutable внутри функции изменит объект снаружи.
-
8. Как работает словарь (dict) под капотом?
dict реализован на основе хеш-таблицы: ключи хешируются, находится индекс в массиве. В Python 3.7+ порядок вставки поддерживается как часть гарантии реализации.
-
9. Что такое list comprehension и генератор выражений?
List comprehension создаёт новый список компактно, генератор выражений возвращает генератор, экономящий память.
squares = [x*x for x in range(10)]
gen = (x*x for x in range(10))
for v in gen:
print(v)
-
10. Как открыть файл и гарантировать его закрытие?
Лучше использовать with — контекстный менеджер, который гарантирует закрытие файла даже при исключениях.
with open('data.txt', 'r', encoding='utf-8') as f:
text = f.read()
# f закрыт автоматически
-
11. Объясните простую реализацию класса и наследование.
Класс описывает поведение и состояние. Наследование позволяет создавать подклассы, переопределять методы.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError
class Dog(Animal):
def speak(self):
return 'woof'
d = Dog('Rex')
print(d.speak())
-
12. Как оптимизировать код при работе с большими файлами?
Читать по строкам, использовать генераторы, буферизацию, избегать загрузки всего файла в память. Для CSV используйте модуль csv с итератором. Для бинарных потоков — memory-mapped файлы (mmap) при необходимости.
-
13. Что такое асинхронность и когда использовать async/await?
Async/await полезны для IO-bound задач: сетевые запросы, работа с БД, веб-серверы. Пример простого асинхронного кода:
import asyncio
async def say(name):
await asyncio.sleep(0.1)
print('Hello', name)
async def main():
await asyncio.gather(say('A'), say('B'))
asyncio.run(main())
-
14. Как сериализовать объекты в JSON и обратно?
Используйте модуль json. Для пользовательских объектов нужно определить способ преобразования в примитивы (dict).
import json
obj = {'a': 1, 'b': [1,2,3]}
s = json.dumps(obj)
obj2 = json.loads(s)
print(obj2)
-
15. Типичный алгоритмический вопрос: найти второй по величине элемент в списке.
Проще всего пройти список один раз, сохраняя два максимума. Вариант за O(n) времени и O(1) памяти:
def second_max(nums):
if len(nums) <= 1:
return None
mx = second = float('-inf')
for x in nums:
if x > mx:
second = mx
mx = x
elif x > second and x != mx:
second = x
return second if second != float('-inf') else None
print(second_max([3, 1, 4, 4, 2])) # 3
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…