Публикувахме условието на четвърта задача. Може да намерите примерния тест в GitHub.
Ако имате въпроси — давайте.
Публикувахме условието на четвърта задача. Може да намерите примерния тест в GitHub.
Ако имате въпроси — давайте.
present()()
да гръмне) нали?for_any()(x)
и for_all()(x)
(за справка вградените функции: any([])
връща False
, а all([])
връща True
)?present()()
трябва да гръмне. Както и ако е някой от другите предикати примерно gt(4)()
, lt(0)(
) и т.н.[]
си е аргумент. Гледам че any()
и all()
връщат грешка. Най-вероятно и нашите така трябва да действат.any
и all
приемаt iterable затова примера е с празният списък, а нашите функции приемат променлив брой аргументи, които достъпваме през predicates (което винаги е налично и е празният списък, ако подадем 0 на брой аргументи), т.е. има просто синтактична разлика.
аха разбрах какво имаш в предвид. Ами гледайки реализацията на any
и all
, предполагам, че for_any()(x)
трябва да връща False
, а for_all()(x)
да връща True
Бихте ли показали по някой и друг пример за отрицание и импликация?
От гледна точка на логиката(онази в дебелите книги):
for_any(*predicates)
→ поне едно от условията в predicates е вярно, т.е. ако няма никакви условия в predicates, то няма нито едно което да е вярно
for_all(*predicates)
→ за всички условия в predicates е вярно, т.е. ако няма условия в predicates, няма такова за което да не е вярно, ерго за всичките е вярно...
@Димо: за отрицанието:
>>> (~gt(0))(1)
False
>>> (~gt(0))(0)
True
>>> (~gt(0))(-1)
True
Относно импликацията и на мен ми е интересно за пример. Как става прилагането ѝ?
a(x) >> b(x)
или (a >> b)(x)
А очаква ли се отрицанието да работи за:
not_binary = ~(eq(0) | eq(1))
Според мен (eq(0) | eq(1))
би трябвало да ти върне, иначе eq(0) | eq(1) | eq(2)
няма да ти работи. Всъщност прилагането на комбинатор в/у предикат(и) трябва да връщат предикат.
Имам един въпрос относно: "Няма значение дали комбинатори ще оценяват предикати, когато това не нужно. Ако a(x)
е False
, то няма значение дали a(x) & b(x)
ще оцени b(x)
".
Това трябва ли да означава, че (от примерите в условието) при
digit = oftype(int) & gt(-1) & lt(10)
digit( 1 + 2j )
е ОК да гърми?
digit( 1 + 2j )
би следвало да се счупи още на oftype(int). Идеята на това е че няма значение след като се счупи на oftype, дали ще проверява и gt и lt или веднага ще върне False.
А в комуналния дух на споделяне на тестове, който имаше предния път: http://paste.debian.net/115671/
Не точно. oftype(int)
няма да се счупи, а ще върне False
, понеже 1 + 2j
не е int
. И точно това ми беше въпросът - какво е правилното поведение?
Според условието, не е проблем програмата да гръмне( не digit( 1 + 2j )
да върне False, а "изгърми" ) понеже не ни задължават да правим lazy evaluation ( digit( 1 + 2j )
ще се оплаче, че не може да сравни int
с complex
при gt
и/или lt
)
От друга страна, ако се направи с "мързеливо оценяване", това ще ни гарантира резултат False
, а не грешка (:
Здравейте
не знам дали аз се бъркам обаче докато гледах условието - "oftype(t)
-- връща дали аргумена е от тип t (проверява с instanceof
)" потърсих нещо за "instanceof" и нищо не намерих :( Да не би да имате предвид isinstance()
??
Поздрави, Никола.
П.С. :Д аргумена :Д
@Кирил: Схванах, лошо ползвам 'счупи' като дума, извинявай. :) Щом не държат на lazy оценяване, значи това няма какво друго да направи освен да хвърли, че не може да сравнява int с complex.
В тестовете на Евгени има assert, който много точно описва изискването за for_any - да "връща True
, ако поне един от предикатите в predicates връща True
за аргумента".
Този тест не минава ако се използва any а не наш си код за обхождане.
Та въпросът ми е в условието стриктна проверка за True
ли се има предвид или "истина"?
def test_for_all_extract(self):
def even(n):
if n % 2 == 0:
return True
else:
return 'banichka s boza'
some_predicate = for_all(pred(even), gt(0), lt(10))
self.assertTrue(all(('banichka s boza', True, True))) #OK
self.assertFalse(some_predicate(3)) #Fails
Още малко тестове(не, че тестват нещо по-различно):
@Александър:
Ползва се така: present()(something)
. Другото е каквото Илиян каза.
Иначе, няма значение какво ще се случи с for_all
и for_any
когато нямат аргументи. Аз бих го направил консистентно с all
и any
. Няма да тестваме.
@Димо, @Илиян:
Ако имаме положително число, искаме то да е 42. Приемаме всякакви неположителни числа:
(gt(0) >> eq(42))(number)
@Димо:
~(eq(0) | eq(1))
трябва да работи.
@Кирил:
Point taken за digit
. Аз съм го направил с "мързеливо оценяване". Вие го направете както искате -- няма да тестваме за това.
@Никола:
Уупс. Не съм писал на Java от години и все още ме избива на instanceof
. Прав си за всичко, което каза -- ще обновя примера.
@Михаил:
Съвършенно прав си. Навсякъде, където съм писал True
съм имал предвид "истина". Аналогично с False
и "неистина". Обнових условието.
@Евгени:
Ако си оправиш теста, ще ти дам точка.
@Димо:
Повече малки тестове обикновено е по-малко големи. Това има две предимства -- (1) стават по-лесни за разбиране, понеже са по-кратки и (2) дават по-ясна идея коя част от кода ти не работи. В твоя случай, ако test_predicates
не мине, не знаеш дали проблема е в lt
, present
или и двете.
Ако разбиеш твоя на по-дребни (и кохезивни) части, ще ти дам точка.
Теста е оправен.
Готово. Въпреки, че според мен имаше някакъв смел творчески порив там... :D
Как да предефинирам операторът ~? А за операторът >> __rshift__
ли да използвам? И по важно как мога да видя всички оператори, които могат да се предефинират?
Ето малко тестове и от мен: http://pastie.org/1854352
Тестовете които завършват на 2 може и да ви фейлват, тъй като не съм сигурен дали се искат от условието. Те искат операциите да работят и ако някой от операндите е функция, а не задължително дефиниран по "нашия" начин предикат.
@Нели
За операторът ~ виж object.__invert__(self)
.
За >>
операторът предположението ти е вярно :)
Иначе ето един добър старт за това къде можеш да видиш всички оператори: http://docs.python.org/py3k/reference/datamodel.html
Според условието на задачата "За нашите цели, "предикат" е функция на един аргумент, която връща True или False." Това значи ли че решението трябва да работи за изрази от вида pr = gt(13) & lambda x: x < 42
? Aко да, какъв тогава е смисъла от pred(function)
?
@Иван:
Не, не значи. Ако искаш да комбинираш gt(13)
с lambda x: x < 42
, то трябва да стане така:
gt(13) & pred(lambda x: x < 42)
Под "функция на един аргумент" визирах математическия термин. Ако искаш по-прецизна дефиниция: обект, с оператор ()
приемащ един аргумент и връщаш истина или неистина.
@Кирил:
Point taken за digit. Аз съм го направил с "мързеливо оценяване". Вие го направете както искате -- няма да тестваме за това.
Тоест няма проблем да гърми, ако му се подаде string, така ли?
Тъй като в един от тестовете на Евгени (всъщност точно този с digit, от примера в условието на задачата):
def tests_from_task(self): digit = oftype(int) & gt(-1) & lt(10) #... self.assertFalse(digit("a"))
Гърми. Силно. Проблем, или не?
Т.е. ще има ли подобни тестове при вас?
не няма да го тестват това. и аз мислех да питам този въпрос ама по думите на Стефан разбрах, че няма да тестват :)
Абе и аз уж така разбрах, ама викам да double-check-на, та да не осера нещо. :)
Айде, тъй да бъде. :)
Хора, при мен гърми ~:
TypeError: bad operand type for unary ~: 'function'
Например
>>> a = ~(lt(10) & lt(20))
или
>>> t = ~~gt(10)
(Последното е подобно на:
>>> not_positive = ~gt(0)
>>> positive = ~not_positive
)
~(eq(0) | eq(1)) #също не работи.
Друг (всъщност подобен) проблем е с
pr = (lambda x: isinstance(x, int)) >> gt(41)
Грешката е:
TypeError: unsupported operand type(s) for >>: 'function' and 'gt'
Някаква идея как да оправя проклетия проблем?
Забележка: използвам отделни класове за gt, lt и т.н., които наследяват базов клас, където са имплементирани &, |, ~ и другите подобни.
@Евгений: Въпрос на имплементация е.
Предполагам, че знам къде ти е проблема, надявам се никой да не ме нахока за този жокер:
#Bla-bla - some code return not self.whatever_you_want #Maybe with ()
return ~self.whatever_you_wantкоето не върви. Същото важи и за другия ти проблем (помни, че >> за предикатите извършва коренно различна функция от нормалния rshift). Ако проблема ти се корени в нещо друго - кофти тръпка.
Успех. :)
П.С. Аз имам един въпрос, предполага ли се, че комбинаторите for_all и for_any трябва да се държат като предикати?
Предполагам, че не, тъй като иначе щяха да са в графата с предикатите, но все пак да питам (не, че има време, май ще го оставя както съм си го написал).
При мен е
return not self(x)
където x е аргумента, който подаваме най-накрая. Примерно:
>>> a = gt(1)
>>> a(10)
x ще е точно това 10.
Освен това използвам вложена функция във функция за тези предефенирания. return not self(x) е точно във вложената функция.
Иначе аз никъде не използвам ~ и >>, а 'not' и 'нещо if нещо else нещо' (заменя се 'нещо' с каквото трябва - страх ме е да го напиша, за да не ме нахокат, въпреки че времето почти изтече).
Трябва да сте влезли в системата, за да може да отговаряте на теми.