Вход | Регистрация

Четвърта задача

Начало: 14.05.2010 09:00

Край: 27.05.2010 18:00

Сега е: 27.09.2013 22:07

Приключи на 27.05.2010

Ще си поиграем с unit тестове, декоратори и метакласове.

unit_converter

Напишете динамичен декоратор unit_converter(a, b), който да приема функция, която връща числов резултат, и обръща резултата й от една мерна единица към друга - например от инчове към сантиметри.

unit_converter(a, b) трябва да конвертира резултата x на функцията по формулата ax + b.

Пример:

@unit_converter(1.8, 32)
def celsius_function():
    return 18.0; # градуси по целзий

>>> print(celsius_function()) # връща градуси по фаренхайт
64.4
# 1.8 * 18.0 + 32 = 64.4

Като всеки добър декоратор, и този трябва позволява декорираната функцията да има произволен брой и вид аргументи.

Unit test

Ваш колега е написал функция is_prime(x), която връща True ако x е просто число.

Не сте сигурни дали функцията работи както трябва, за това трябва да напишете unit тест клас, наречен IsPrimeTest, който да тества функцията.

Вашият клас трябва да има следните тестове:

  • testBasic(), който проверява поведението на is_prime() при 1, 2, 4, 6 и 7
  • testNegative(), за поведението на is_prime() при отрицателни числа (is_prime() би трябвало да върне False)
  • testNonNumber(), за поведението на is_prime() при не-числа (is_prime() ще хвърли exception)
  • testRandom(), за поведението на is_prime() при 10,000 случайно генерирани числа, които да сравнявате с ваша имплементация на функцията с друго име

Трябва да спазвате протокола за unit тестове на Python, включително да наследявате правилния клас.

Функцията is_prime(), която трябва да тествате, се намира в примерния тест p10sample.py. За да я използвате напишете

from p10sample import is_prime.

Метакласове

Напишете метаклас NegativeMeta, който за всеки метод x от оригиналния клас да създава метод not_x, който да приема същите аргументи, но да връща отрицателния булеви резултат (с not).

Пример:

class Comparer(metaclass = NegativeMeta):
    def __init__(self, a):
        self.a = a

    def is_bigger_than(self, b):
        return self.a > b

>>> twenty = Comparer(20)
>>> print('not_is_bigger_than' in dir(twenty))
True
>>> print(twenty.is_bigger_than(40))
False
>>> print(twenty.not_is_bigger_than(40))
True

Няма нужда да проверявате дали вече има метод с име not_x. Методите, започващи с __ също можете да оставите на мира.

Метакласове 2

Напишете втора версия на NegativeMeta, наречена NegativeMetaDynamic, която се държи по същия начин, но изпълнява методите not_x динамично, вместо да ги създава при дефинирането на класа.

Пример:

class Comparer2(metaclass = NegativeMetaDynamic):
    def __init__(self, a):
        self.a = a

    def is_bigger_than(self, b):
        return self.a > b

>>> twenty = Comparer2(20)
>>> print('not_is_bigger_than' in dir(twenty)) # !!!
False
>>> print(twenty.is_bigger_than(40))
False
>>> print(twenty.not_is_bigger_than(40))
True

Примерен тест

Връзка: p10sample.py

Тестът може да изпълните като свалите p10sample.py, заедно с него в една директория запазите своето решение, именувано p10.py и изпълните p10sample.py. Крайната ви цел е да получите OK някъде из резултата.

Не забравяйте да използвате Python 3.

Тестът не гарантира, че ще получите всички точки по задачата, но поне ще ви гарантира, че не сте допуснали глупава грешка, която да ви коства всички точки.

Успех!