Fork me on GitHub
4/2/2010

Вопросы и задания по Python

Меня периодически спрашивают о тестовых заданиях по Python-тематике. Я решил обобщить вопросы и написать их в одном месте. Я не использую эти вопросы и задания в собеседованиях, но использую при обучении.

Типы данных, основные конструкции

  1. Как получить список всех атрибутов объекта
  2. Как получить список всех публичных атрибутов объекта
  3. Как получить список методов объекта
  4. В какой "магической" переменной хранится содержимое help?
  5. Есть два кортежа, получить третий как конкатенацию первых двух
  6. Есть два кортежа, получить третий как объединение уникальных элементов первых двух кортежей
  7. Почему если в цикле меняется список, то используется for x in lst[:], что означает [:]?
  8. Есть два списка одинаковой длины, в одном ключи, в другом значения. Составить словарь.
  9. Есть два списка разной длины, в одном ключи, в другом значения. Составить словарь. Для ключей, для которых нет значений использовать None в качестве значения. Значения, для которых нет ключей игнорировать.
  10. Есть словарь. Инвертировать его. Т.е. пары ключ: значение поменять местами — значение: ключ.
  11. Есть строка в юникоде, получить 8-битную строку в кодировке utf-8 и cp1251
  12. Есть строка в кодировке cp1251, получить юникодную строку

Функции

  1. Написать функцию, которой можно передавать аргументы либо списком/кортежем, либо по одному. Функция производит суммирование всех аргументов.

    >>> f(1, 2, 3)
    6
    >>> f([1, 2, 3])
    6
    >>> f((3, 5, 6))
    14
    >>> f(3, (5, 6))
    14
  2. Написать функцию-фабрику, которая будет возвращать функцию сложения с аргументом.

    >>> add5 = addition(5) # функция addition возвращает функцию сложения с 5
    >>> add5(3) # вернет 3 + 5 = 8
    8
    >>> add5(8) # вернет 8 + 5 = 13
    13
    
    >>> add8 = addition(8)
    >>> add8(2) # вернет 2 + 8 = 10
    10
    >>> add8(4) # вернет 4 + 8 = 12
    12

    Написать варианты с обычной "внутренней" и анонимной lambda-функцией.

  3. Написать фабрику, аналогичную п.2, но возвращающей список таких функций

    >>> additionals = addition_range(0, 5) # список из функций сложения от 0 до 5 включительно
    

    т.е. аналогичное [add0, add1, add2, add3, add4, add5]

  4. Написать аналог map:

    • первым аргументом идет либо функция, либо список функций
    • вторым аргументом — список аргументов, которые будут переданы функциям
    • полагается, что эти функции — функции одного аргумента
    >>> mymap([add0, add1, add2], [1, 2, 3])
    [(1, 2, 3), (2, 3, 4), (3, 4, 5)]

    в данном случае "развернутая" запись будет: [(add0(1), add0(2), add0(3)), (add1(1), add1(2), add1(3)), (add2(1), add2(2), add2(3))]

Итераторы

  1. Написать функцию-генератор cycle которая бы возвращала циклический итератор.

    >>> i = iter([1, 2, 3])
    >>> c = cycle(i)
    >>> c.next()
    1
    >>> c.next()
    2
    >>> c.next()
    3
    >>> c.next()
    1
  2. Написать функцию-генератор chain, которая последовательно итерирует переданные объекты (произвольное количество)

    >>> i1 = iter([1, 2, 3])
    >>> i2 = iter([4, 5])
    >>> c = chain(i1, i2)
    >>> c.next()
    1
    >>> c.next()
    2
    >>> c.next()
    3
    >>> c.next()
    4
    >>> c.next()
    5
    >>> c.next()
    Traceback (most recent call last):
      ...
    StopIteration

Для функций и итераторов написать доктесты

Модули

  1. У нас есть импортированный модуль foo, как узнать физический путь файла, откуда он импортирован?
  2. Из модуля foo вы импортируете модуль feedparser. Версия X feedparser'а есть в общесистемном каталоге site-packages, версия Y — рядом с модулем foo. Определена переменная окружения PYTHONPATH, и там тоже есть feedparser, версии Z. Какая версия будет использоваться?
  3. Как посмотреть список каталогов, в которых Python ищет модули?
  4. У вас есть модуль foo, внутри него импортируется модуль bar. Рядом с модулем foo есть файлы bar.py и bar/__init__.py Какой модуль будет использоваться.
  5. Что означает и для чего используется конструкция __name__ == '__main__'

Классы

  1. Написать базовый класс Observable, который бы позволял наследникам:

    1. при передаче **kwargs заносить соответствующие значения как атрибуты
    2. сделать так, чтобы при print отображались все публичные атрибуты
    >>> class X(Observable):
    ...     pass
    >>> x = X(foo=1, bar=5, _bazz=12, name='Amok', props=('One', 'two'))
    >>> print x
    X(bar=5, foo=1, name='Amok', props=('One', 'two'))
    >>> x.foo
    1
    >>> x.name
    'Amok'
    >>> x._bazz
    12
  2. Написать класс, который бы по всем внешним признакам был бы словарем, но позволял обращаться к ключам как к атрибутам.

    >>> x = DictAttr([('one', 1), ('two', 2), ('three', 3)])
    >>> x
    { 'one': 1, 'three': 3, 'two': 2}
    >>> x['three']
    3
    >>> x.get('one')
    1
    >>> x.get('five', 'missing')
    'missing'
    >>> x.one
    1
    >>> x.five
    Traceback (most recent call last):
      ...
    AttributeError
  3. Пункт 2 с усложнением: написать родительский класс XDictAttr так, чтобы у наследника динамически определялся ключ по наличию метода get_<KEY>.

    >>> class X(XDictAttr):
    ...     def get_foo(self):
    ...         return 5
    ...     def get_bar(self):
    ...         return 12

    >>> x = X({'one': 1, 'two': 2, 'three': 3}) >>> x X: { 'one': 1, 'three': 3, 'two': 2} >>> x['one'] 1 >>> x.three 3 >>> x.bar 12 >>> x['foo'] 5 >>> x.get('foo', 'missing') 5 >>> x.get('bzz', 'missing') 'missing'
  4. Написать класс, который регистрирует свои экземпляры и предоставляет интерфейс итератора по ним

    >>> x = Reg()
    >>> x
    <Reg instance at 0x98b6ecc>
    >>> y = Reg()
    >>> y
    <Reg instance at 0x98b6fec>
    >>> z = Reg()
    <Reg instance at 0x98ba02c>
    >>> for i in Reg:
    ...     print i
    <Reg instance at 0x98b6ecc>
    <Reg instance at 0x98b6fec>
    <Reg instance at 0x98ba02c>

Написать юнит-тесты, за основу брать тесты выше, но не ограничиваясь ими.

Метаклассы и дескрипторы

Вопросы:

  1. Для чего используются, какие аргументы получают, что должны возвращать: методы __new__ и __init__ классов
  2. Какие аргументы получает __new__ и __init__ у метакласса?

Задания:

  1. Реализовать дескрипторы, которые бы фиксировали тип атрибута

    >>> class Image(object):
    ...     height = Property(0)
    ...     width = Property(0)
    ...     path = Property('/tmp/')
    ...     size = Property(0)

    >>> img = Image() >>> img.height = 340 >>> img.height 340 >>> img.path = '/tmp/x00.jpeg' >>> img.path '/tmp/x00.jpeg' >>> img.path = 320 Traceback (most recent call last): ... TypeError
  2. Реализовать базовый класс (используя метакласс), который бы фиксировал тип атрибута

    >>> class Image(Object):
    ...     height = 0
    ...     width = 0
    ...     path = '/tmp'
    ...     size = 0
    
    >>> img = Image()
    >>> img.height = 340
    >>> img.height
    340
    >>> img.path = '/tmp/x00.jpeg'
    >>> img.path
    '/tmp/x00.jpeg'
    >>> img.path = 320
    Traceback (most recent call last):
      ...
    TypeError
  3. Реализовать базовый класс (используя метакласс) и дескрипторы, которые бы на основе класса создавали SQL-схему (ANSI SQL) для модели:

    >>> class Image(Table):
    ...     height = Integer()
    ...     width = Integer()
    ...     path = Str(128)
    
    >>> print Image.sql()
    CREATE TABLE image (
        height integer,
        width integer,
        path varchar(128)
    )

    реализовывать [NOT] NULL, PRIMARY KEY, FOREIGN KEY, CONSTRAINTS не нужно. Достаточно реализации двух типов: Integer и Str.

Комментарии

Все статьи