Шеста задача

  1. Здравейте,

    В шеста задача за класът Vec2D пише, че трябва да поддържа събиране и изваждане на вектор със скалар. Тъй като в математиката не са дефинирани тези операции, искам да попитам как трябва да се извърши - скаларът да се добави към/извади от първата или от втората координата, или и от двете заедно?

  2. След като contents може да съдъРжа (пропуснали сте р-то в условието на задачата :) ) само инстанции на WorldObject (или на негови наследници) това означава ли, че не може да съдържа PythonPart или и PythonPart наследява WorldObject?

  3. Ето го и моят коментар по задачата:

    1. В условието според мен (може и да греша) малко странно са смесени някакви неща приличащи на интерфейси с имплементации в смисъл, че на методите някъде сте писали self, някъде не. Но това може и да е просто, че не съм свикнал да гледам интерфейси на python.

    2. В примерните тестове реално се появява ограничение от гледна точка на имплементация на Vec2D - по-конкретно това че присвоявате x, y = Vec2D(...). Това макар и донякъде да звучи доста логично принципно не мисля, че в условието беше указано, че е нужно. (Например моята оригинална имплементация не го поддържаше, но заради тестовете я промених). Също преди малко забелязах, че за векторите е добавено условие да поддържат унарен минус - нещо, което го нямаше в по-ранната версия на условието (което между другото не е обновено в github). Във връзка с това не знам как може да се направи така, че някой предал домашното да може да разбира за промени по условието, понеже в github има history, но тук не. Не мисля, че трябва човек редовно да проверява ръчно за промени, ако вече си е изпратил домашното.

    3. Pep8 - Карате ни се, когато не го спазваме, в случая забелязвам 3 грешки в публичния тест: 3ти ред липсват 2 нови реда; 29ти ред е излишен; 37ми има нужда от още един ред преди него

    4. coords vs coordinates - вие ползвате първото и в случая наистина на мен ми звучи по-добре, макар че обикновено ни казвате да не ползваме съкращения. С цел да не се смесват двете навсякъде и аз съм ползвал краткия вариант. Ако считате, че е по-добре да се смени на дългия може да кажете.

    5. Проверка за посока - това може би е тъп въпрос, но все пак - обикновено ни казвате да очакваме само валиден вход, но в случая трябва ли да правим проверка за валидност (че посоката е някое от Python.UP, Python.DOWN, Python.LEFT, Python.RIGHT, а не нещо ваше)?

    6. Ще се интересувате ли дали по средата на някое наше действие някоя стойност е странна, тоест ако хвърляме изключение ще се гледат ли някакви стойности около него дали са валидни. Във връзка с това на следващата лекция, или в коментар бих се радвал ако пак припомните малко за Better Ask For Forgiveness Than Permission срещу Look Before You Leap, понеже както тук, така и в предишни домашни доста по-лесно ми се е струвало просто в началото да проверя за валидност и да възбудя някое изключение вместо да правя всякакви неща и после да се опитам да променя изключението, което може да се хвърли.

    7. В тестовете на 27ми ред използвате py.head, атрибут, който никъде не е казан, че трябва да присъства. Също в дадени имплементации наличието на клас PythonHead може да е безсмислено.

  4. Благодаря за въпросите и критиката.

    1. Малко странно е, наистина. Не исках да описвам всичко в списък и се спрях на това подобие на псевдо-код. self вече е добавен навсякъде за консистентност.

    2. Хората предали домашното се броят на 2 пръста и те са получили коментар за промяната :-)

    3. Ще бъде поправено скоро.

    4. coords си е супер. Аз лично съм против само за трибуквените съкращения. В противен случай с променливи като python_coordinates и maybe_cell_is_empty доста лесно се запълват 80 символа с един израз. Като цяло не мисля че трябва да се отнасяме фанатично към съкращенията и просто трябва да се намери някакъв приемлив баланс между ясността на имената и четимостта.

    5. Не е нужно да се прави проверка за валидност.

    6. В общият случай искай прошка. Няма да се очаква консистентно състояние на света след Death, но все пак при някои изключения LBYL е задължително, например когато трябва да хвърлиш ValueError.

    7. Това е наследство от старото, доста по-сложно условие на задачата. Ще бъде премахнато от теста скоро. И все пак да си пазиш връзки към главата и частите в инстанцията не е чак толкова лоша идея. Не виждам как можеш да имаш имплементация без PythonHead. В условието е указано че се прави разлика между частите на питона и главата му. Освен това ако си правите визуализация си е доста полезно ако главата изглежда по различен начин.

  5. print(food) извежда <__main__.Food object at 0x00000000029847F0> - това е резултатът, който получаваш като си принтираш даден обект от клас Food.

    В моя случай 0x00000000029847F0 е шеснайсетично представяне на id(food) - 43534320. При тях те пускат в интерактиваната конзола някакви подобни неща и получават подобни резултати.

    Синтаксисът е: >>> input output

    Тоест това е просто някаква репрезентация на храната - дали са го за илюстрация. Иначе как точно са постигнали това at v(0, 0) и аз не знам точно, Людмил може да ни обясни, щом ни е интересно. Иначе за самото решение на задачата не мисля, че е от значение.

  6. предефинирал съм __repr__ метода:

    на Vec2D: def str(self):
    return "v(%d, %d)" % (self.x, self.y)

    def __repr__(self):       
        return "<%s %s>" % (self.__class__.__name__, self.__str__())
    

    на WorldObject: def repr(self): return " at %s" % (self.class.name, str(self.coords))

    Това, разбира се, не е задължително и можете да не го правите.

  7. Между другото ето ако искате един прост конзолен интерфейс - има си функция за принтиране на света, както и функция, която ви пуска игра с default-ни контороли wasd - можете да я ползвате за дебъг. При изключение не спира, а просто го изписва на екрана.

    На 8ми ред може да смените първия елемент с името на класа, който ползвате и на 22ри може би трябва да го промените в зависимост от вашата матрица за съхранение. :smile:

    Note: Писал съм я за windows - тоест ако сте на Linux/ OS X може да закоментирате 17 ред и да откоментирате 18. Същото и с 37 и 38 ред.

  8. Как трябва да се държи програмата в случай, в който първоначално поставяме змията върху клетки, които съдържат инстанции на класа Food - дали вземаме автоматично енергията от тях и я добавяме към енергията на змията? Или напротив - не се случва нищо особено и продължаваме по описания начин?

  9. Аз не разбрах - индексацията от 0 или от 1 започва? Спрямо картинките би трябвало да започва от 1, но от изречението: "Отрицателни координати .... хвърлят IndexError" си правя извода, че (0,0) са валидни координати, защото 0 не е отрицателно число.

  10. @Христина По принцип не може да има две неща в една клетка и в нашата имплементация това replace-ва храната. Бройте го за недефинирано поведение. Няма да има такъв тест.

    @Красимира (0, 0) са валидни координати. Мисля че картинките започват от (0, 0) но може и да не съм ги копирал правилно.

  11. contents може да съдържа само инстанции на WorldObject (или на негови наследници).

    Очевидно го пише достатъчно ясно, но поне на мен ми се струва като лоша идея правенето на обект със смисъл на 'нищо' различен от None тоест да правя примерно EmptyWorldObject(), просто WorldObject() или нещо подобно.

    Тоест може ли да има изключение по тази точка - да може contents да бъде None за празните клетки?

  12. Имам въпрос, как да подтисна изключение. Имам try: statement, които хвърля IndexError except IndexError: raise Death

    Обаче после се принтира първо IndexError и пише, че по време на обработката му е възникнал и Death и принтира и Death.

    Как да му забраня да принтира IndexError-а ?

  13. Въпросчета:

    • Главата на питона трябва да е там, където е посочено с coords
    • Останалите части на питона трябва да са подредени в права линия и в посока обратна на direction

    Ако не се събира змията? Death или няма да има такъв тест, или го оставяме като недефинирано?

    Друго.

    old_direction = py.direction Това е на ред 23 май в тестовете. В условието пише, че задължителни полета са size и константите. Пък и на мене не ми трябва никъде засега и не виждам смисъл да си го пазя допълнително :\

  14. @Людмил Имам коментари по тестовете към домашното:

    • test_python_movement_basic: direction се е появило ~2 часа преди края и изобщо каква е ползата от това property дори в теста?
    • test_snake_death: Движение нагоре обикновено се дефинира с вектора (0, 1). Щеше да е добре да се спомене в условието някаква ориентация на света(примерно "горният ляв ъгъл е с координати (0, 0)")
  15. Аз иначе не съм съгласен с това "квадратна матрица от Cell обекти" да има координати не като на матрица. Вярно че има легаси, но биваше да е упоменато точно в условието, а не в примера понеже чак сега му обърнах внимание :/.

    ПП иначе тестовете са си ОК, с изключение на повторението на Python.DOWN ;)

Трябва да сте влезли в системата, за да може да отговаряте на теми.