Не, не е добра идея. :)
Да щеше да е объркващ, т.к. нямаше да е ясно какво става с нещото, на което го прилагаме.
Отговора следва от това, че ползваме immutable обекти.
Не, не е добра идея. :)
Да щеше да е объркващ, т.к. нямаше да е ясно какво става с нещото, на което го прилагаме.
Отговора следва от това, че ползваме immutable обекти.
И дори, още по-коварно:
balance = getBalance()
print(balance) # -10
absolute = abs(balance)
print(balance) # 10
Това би било сериозен WTF момент.
Всъщност Кирил наистина не е разбрал правилно въпроса ми и по конкретно: трябва ли обектите от тип Lazy да поддържат операции като например повдигане на степен, комплексно спрегнато и тн., които не са описани в условието на задачата, но все пак се извършват върху обикновените числа?
Ако не е описано в условието на задачата, значи не трябва.
Добре, мерси.
Мкей, ето още малко тестове и от мен - http://paste.debian.net/114590/ ... не че тестват нещо твърде много повече от показаните досега, но отвътре ми идеше да ги групирам по този начин; мисля, че Александър Велин би казал, че това показва някаква лека форма на CDO у мен ;) А, да, и ако някой не разбира защо тестовете в ReflectedTests не минават върху неговото решение - спокойно, няма проблем, всъщност това като че ли всъщност не се изисква от условието на задачата, макар че и някои от предишните пуснати тестове го проверяват...
А сега и мъничко коментарче върху самото условие: аз ли нещо пропускам, или фразата 'не забравяйте за "десните" и "левите" оператори' всъщност няма много смисъл в случая? :) Нашите класове не се занимават с разпознаване на лексеми и граматически изрази; за това разчитаме на интерпретатора, нали?
Каква е логиката 5 + Lazy(5) да гърми, ако Lazy(5) + 5 минава?
При твоето решение минават ли reflected? Доколкото разбирам за какво се грижи интерпретатора, то той ще търси дефиниран оператор в int/complex/... и като не го намери ще търси точно reflected в Lazy...
При моето решение има reflected; да, няма логика да няма, особено като се вземе предвид колко лесно се реализират. Това, което исках да кажа, е, че в условието от организаторите на курса няма изискване за reflected ops, така че е напълно възможно решение, което да бъде прието от тях, да не успее да мине всички наши тестове - затова предупреждавам, да не се шашкат хората, ако тяхното се окаже такова :)
...и затова в моя test suite ги изведох в отделен клас.
Всъщност, твоите "reflected" са част от условието. Трябва да минават. Зачетете се малко по-внимателно и обърнете внимание на примерите.
Иначе.
Когато Python види
Lazy(5) + 10
Той изпълнява
Lazy(5).__add__(10)
Аналогично, когато види:
10 + Lazy(5)
Той изпълнява:
10.__add__(Lazy(5))
Което, съответно, не работи съвсем. Ключовата дума е __radd__
. С търсене в документацията ще се справите сами.
За справка, __add__
е "левия оператор". __radd__
е "денсия".
Уф. Да, разбира се, в пример в условието го има. Извинявам се за объркването :)
Значи това сте имали предвид под "ляв" и "десен" оператор; аз мислех, че става дума за асоциативността - което действително е работа на интерпретатора. А думата "reflected" я взех направо от http://docs.python.org/py3k/reference/datamodel.html#special-method-names - затова не направих връзката между "десен" и това "r" :)
Ако имаме примерно p = Lazy(10) + Lazy(5), и следкато напишем q = p + Lazy(24), трябва ли да се вика p.force() при създаването на q.
x|
"Бинарни (двуместни) оператори: +, -, *, /, //, %
Те се прилагат на двойка "мързеливи" числа или на "мързеливо" и обикновено число. Всички оператори трябва да връщат нова инстанция на мързеливо число. Новото мързеливо число трябва да пази информация за двете числа и оператора, но да НЕ прилага оператора на числата. Целта е "мързеливото" число да изглежда като двоично дърво, чиито поддървета са мързеливи [или обикновено] числа, а във възлите има оператори."
Задължително ли трябва вътрешното представяне на Lazy да е дърво? Може ли да изпозваме, примерно, стринг?
Четете ги тия условия...
Можете да подходите към задачата по различни начини. Някои идеи, които можете да ползвате са:
Всъщност ако греша, нека ме поправят, но као цяло според мен пуснатите няколко теста тук са достатъчно, за да прецните дали сте го написали както се изисква за пълен брой точки. А на тема кое би било оптималното представяне предполагам може да се водят пространни задълбочени спорове. Тука влиза и разбира се какво смята човек за оптимално дали по-компактно като памет или по-бързо, или по-малко като код... Разни хора :)
Още един тест, за който се сещам е да се направят няколко force-а и да се провери колко пъти се изчислява числото, което някак си не ми се изясни съвсем... Убедени ли сте, че lazy трябва да стане обикновено след като се force-не? Аз нещо не съм...
@Живка:
Това, което Виктор казва е, че не трябва да се вика force
; q
трябва да бъде мързеливо.
@Светослав: Свободни сте да го имплементирате както искате. Но имплементация с низове ще ти донесат повече проблеми отколкото ползи.
@Евгени: В конкретния случай бих заложил на четимост и простота на решението :)
@Станко:
Lazy
става обикновено число след като се force
-не и няма логика force
да се вика няколко пъти.
@Йоан: последното изречение трябва да означава, че след като извикаме веднъж метода force(), например:
five = Lazy(5)
five.force()
a) то тогава името five ще сочи към 5
или
b) five.force() ще запази изчислената стойност и когато извикаме отново five.force(), ще ни бъде върната запазената стойност?
Здравейте, имплементирах по-голямата част от домашното и за моя радост някои тестове от качените пасват... Проблемът ми обаче е когато имам нещо от следния тип:
a = Lazy(10) + Lazy(20)
a.force()
или
нещо = Lazy(100)
друго = Lazy(нещо)
и се опитам да извикам
друго.Форсе()
Съобщението е : <main.Lazy object at 0x018909B0>
Какъв е проблемът според вас : нещо трябва да добавя в конструктора за да прихваща този случай или логиката ми където съхранявам оператор и самите числа като негови деца в бинарно дърво нещо не е много логична :)Помогнете , че релииза наближава :)
Поздрави, Никола.
Във втория случай вероятно не правиш проверка дали wrap-ната стойност (това, което се подава като аргумент на конструктура) е просто число (в смисъла на вградения тип) или е Lazy. Първият случай сигурно е свързан с вторият или вътрешната ти имплементация пропуска да извика force някъде.
Малко уточнение какво трябва да връща?
lazy_number = Lazy(3)
three = bool(lazy_number)
print(three)
bool(Lazy(3)) -> bool(3) -> True
@Йоан: Отговорът ти повтаря този на Евгений, който ми се струва неясен и затова зададох въпроса отново.
Ивайло е написал точно това, което имах предвид...
Така-аа, имам два въпроса: 1) Ясно е, че при:
>>> lazy_number = Lazy(8) + Lazy(42)
>>> number = lazy_number.force()
>>> print(number)
ще се изведе: 50 и типът на number е int. Но какво трябва да представлява lazy_number след force() и какво трябва да съхранява? Първи вариант е 50, т.е. пресметнатата стойност. Втори вариант ще бъде: '8 + 42'. Написал съм втория вариант, но ако съм сбъркал и трябва първия - няма проблем. Между другото типа и в двата варианта е Lazy, нали?
2) Имам малко проблемче с булевите операции (примерно and): Опитах се да предефенирам and(), но при
>>> boo = Lazy(True) and Lazy(False)
ми дава
>>> boo
False
Което донякъде е очевидно, че е False, но аз все пак очаквах да почне да го пресмята чак след като му дам force(), а не веднага.
Освен това явно въобще не влиза в and, защото сложих един print('Boo!') вътре, ама той въобще не се принтва. Ето го кода на and():
def __and__(self, other):
print('Boo!')
result = bi_op(self, 'and', other)
return Lazy(result)
функцията bi_op е външна функция (използва се за бинарните операции) и трябва да направи result на "(True) and (False)", ако се дадат self като Lazy(True) и other като Lazy(False).
P.S. И да, работя със стрингове - оказа се доста лесно, не се налага да си блъскам главата в дървета и да се чудя как да ги обходя. Освен с True и False, други сериозни проблеми не съм срещнал (или поне такива, които да не съм решил).
Така и не можах да разбера откъде идват проблемите със стрингове. Като изключим проблема с булевите операции, всичко останало беше лесно и имаше доста място за по-оптимизирано писане.
@Евгений: Доколкото си спомням дефинирането на and метода се отнася за побитово И (за оператора &).
Мда, и Гугъла от това казва. И с & стана (изписа си 'Boo!'-то). Но няма ли начин да се предефенира и and, or и not?
Все пак благодаря Ивайло.
Но по-належащия въпрос е все пак първият, тъй като от това какво точно прави force() зависят поне няколко функции (например >, <, == и другите подобни).
Аз може ли да помоля, ако е възможно да увеличите крайния срок за изпращане на домашното. Благодаря предварително :)
Трябва да сте влезли в системата, за да може да отговаряте на теми.