Найти - Пользователи
Полная версия: Программа определения ФАВ в строке
Начало » Python для новичков » Программа определения ФАВ в строке
1 2 3 4 5
Ed
Alex_Kutsan
Я всё пытаюсь разобратся в re.sub и в reduce , но у меня ничего не вышло, хелпы мне непомогают, в них что-то совсем непонятное наисано.
reduce в моем случае - это не стандартная функция reduce, про которую вы прочитали. См. код ниже, я ее переименовал, чтобы вам было легче понять. Что делает sub вам нужно таки попытаться разобраться самому. Если трудности с английским, то найдите русскую книжку по Питону и почитайте. Я вряд ли расскажу лучше, чем в документации.

Ну это ладно ещё, просто решение не верно т.к мы делаем функцию без правила экономии скобок( это условие)
Во-первых я показал направление мысли, а не давал готового решения. Во вторых если понимать как это работает, то исправить проблем нет. Вот вам тоже самое без экономии скобок:
def is_prop_formula(string):
def reducE(string):
result = re.sub("\(&[A-Z]\)|\([A-Z]>[A-Z]\)|\([A-Z]<[A-Z]\)|\([A-Z]=[A-Z]\)|\([A-Z]_[A-Z]\)|\([A-Z]\)", "X", string)
if result != string:
return reducE(result)
return result
return reducE(string) == "X"
тоесть выражение вида (A=B)>(&C<D)=C=T>Z") будет являтся ошибкой.
Если исправить:
(((A=B)>((&C)<D))=(C=(T>Z))) вот теперь правильно.
Любой каприз!
> print is_prop_formula("(A=B)>(&C<D)=C=T>Z")
False
> print is_prop_formula("(((A=B)>((&C)<D))=(C=(T>Z)))")
True
Что такое False и True вы, надеюсь, понимаете?
Alex_Kutsan
Конечно понимаю, сейчас постараюсь разобратся с re.sub
Спасибо
Ed
Вам для начала нужно разобраться с re, а re.sub - это уже частности.
Читайте здесь: http://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D0%BE%D0%B5_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5
Griffon
# 1
class BrokenEgg(Exception):
pass
# 2
class Brain_breacker:
def __init__(self):
# 3
self.test_exp = ""
self.expect_operator = 0
self.braces = 0
# 4
self.operators = ("!", "&", "|", "==", "_")
self.operator_leters = ("!", "&", "|", "=", "_")
self.prefix_operators = ("!")
self.var_begining = ("x", "y")

def is_var(self, i):
# 5
if self.test_exp[i] in ("x", "y"):
return True
return False

def add_var(self, i):
# 6
return i+1

def check_operator_expection(self, i):
# 7
if self.expect_operator:
raise BrokenEgg("Expect operator after '%s'." % self.test_exp[:i])

def check_other_expection(self, i):
# 8
if not self.expect_operator:
if self.test_exp[i] in self.prefix_operators:
return True
raise BrokenEgg("Don't expect operator after '%s'." % self.test_exp[:i])

def is_operator(self, i):
# 9
if self.test_exp[i] in self.operator_leters:
return True
return False

def add_operator(self, i):
# 10
j = i
buf = ""
while self.test_exp[j] in self.operator_leters:
buf += self.test_exp[j]
j += 1

if buf in self.operators:
return j
else:
raise BrokenEgg("Operator '%s' doesn't exist." % buf)

def start(self, expression):
# 11
self.test_exp = expression
i = 0
while i < len(self.test_exp):
# 12
if self.test_exp[i] == "(":
# 13
self.check_operator_expection(i)
# 14
self.braces += 1
# 15
self.expect_operator = False
# 16
i += 1
# 17
continue
# 18
if self.test_exp[i] == ")":
self.braces -= 1
# 19
self.expect_operator = True
i += 1
continue

# 20
if self.is_var(i):
self.check_operator_expection(i)
i = self.add_var(i)
self.expect_operator = True
continue
# 21
if self.is_operator(i):
self.check_other_expection(i)
self.expect_operator = False
i = self.add_operator(i)
continue
# 22
if self.test_exp[i] == " ":
i += 1
continue
# 23
raise BrokenEgg("Unexpectable simbol '%s'." % self.test_exp[i])
# 24
if self.braces:
raise BrokenEgg("Something wrong with braces.")
return True

# 25
def test(text, i = [0]):
# 26
i[0] += 1
print ">Test number %s:" % i[0]
print "Test expression is '%s'." % text
# 27
bb = Brain_breacker()
# 28
try:
bb.start(text)
print "It's allright with '%s'" % text
except BrokenEgg as e:
print e
print ""

# 29
test("(!x == y & x ! x & !(!x & !y))")
test("(!x + y & x ! x & !(!x & !y))")
test("(!x == y & x = x & !(!x & !y))")
test("(!x == (y) & (x ! x & !(!x & !y)))")
test("(!x == (y & (x ! x & !(!x & !y)))")
1) Создаём класс исключения. (Читать доку по исключениям)
2) Создаём класс с именем Brain_breacker. Для студента имя самое оно. :)
3) Обьявляем конструктор класса. Три пермененные нам понадабятся дальше.
4)
operators - списко операторов которые можно использовать.
prefix_operators - список операторов которые можно использовать как префикс к выражению, или переменной.Например “!х”.
operators_leters - список всех символов из которых могут состоять операторы.
var_begining - список первых символов переменных. Например переменные могут начинаться на прочерк, и букву. Вообще-то это должно быть регулярное выражение, ибо если я захочу реализовать правило описанное предложением ранее, то это будет очень большой список Но в данном случае пойдёт.
5) Метод (так называются функции классов) принимает индекс символа в исходном выражении. Проверяет начинается ли с данного символа переменная. Если да то дальше надо читать переменную.
6) Метод читает переменную и возвращает индекс следующего за именем переменной символа. В данном случае у нас переменные односимвольные, потому метод вообще можно было не создавать. Но если имена переменных будут длинные, то именно в этой функции будет задано правило её чтения.
7) Метод проверяет ожидался ли оператор и если да, то вызывает исключение. Код прерывает исполнение. Исключение ловится ключевым словом except и код продолжает исполнятся аж оттуда.
8) Метод проверет ожидалось ли что-либо иное кроме оператора. Если да, то бросаем исключение. Но. Если же мы получили префиксный оператор, хоть и ожидали не оператор, мы продолжаем выполнение программы.
9) Метод определяет оператор начался, или нет.
10) Метод читает оператор. Возвращает индекс следующего за оператором символа. Если же оператора нет в списке операторов, то генерирует исключение (raise).
11) Итак начинаем проверку выражения. Ставим индекс в ноль, создаём цикл который завершится когда индекс станет больше длины выражения.
12) Если символ открывающей скобки.
13) Вдруг мы в прошлый раз обработали переменную, или закрывающую скобку, и ожидали увидеть дальше оператор? Вот и проверяем, а не ожидался ли оператор? Если да то выражение ошибочно, и мы должн вывести соответствующее сообщение. (смотреть №7)
14) Увеличим счётчик скобок.
15) За открытой скобкой мы ожидаем не оператор, а что-то другое (исключение префиксный оператор. №8).
16) Перейдём на следующий символ.
17) Запустим цикл заново.
18) Попался символ закрывающей скобки. Уменьшим счётчик скобок.
19) После закрывающейся скобки мы ожидаем увидеть оператор.
20) Кажется мы наткнулись на начало именни переменной. А может быть мы уже прочли одну переменную, или закрыли скобку? Может мы ждём оператор? А если нет? Дальше читаем переменную, и ждём что за переменной последует оператор, или закрывающая скобка (она же не проверяет ожидание оператора).
21) А вот и начался оператор. Если сдесь ожидалось что-нибудь другое, а не оператор, например оператор уже был, то это ошибка. Дальше ожидаем не оператор.
22) Пробел.
23) Если мы дошли сюда, то значит в выражении есть символ на который не начинаются переменные и операторы, и это точно не скобки и не пробел. То есть это ошибка! Неизвестный символ.
24) Мы вышли из цикла здоровыми и невредимыми. Но все ли скобки закрыты (открыты)?
25) Функция проверки выражения.
26) Маленькая хитрость.
27) Создаём экземпляр класса.
28) Метод проверки запускаем в блоке try except. Как так, ты ещё не прочитал про исключения? Просил же первой строчкой. Если во время выполнения программы возникнет исключение (именно наше), то мы прыгнем сразу за блок except. И соответственно не увидим слов “Всё хорошо”. “print e” выведет текст который мы писали генерируя исключение.
29) Ну чтож. Поехали :)

Почему именно так? Потому что добавив всего пару методов можно построить собственный интерпретатор. Вместо имён переменных можно подставлять значения. В общем вплоть до вычисления выражения.

Надеюсь это было полезно. Но!
Но в контексте поставленной задачи, код Ed'a намного лучше. Вот сам сейчас пытаюсь разобрать эту регулярку. В последний раз юзал регулярные выражения в 2006 на PHP. :)
Alex_Kutsan
Знаете если чесно я почти понял что это re.sub("\(&\)|\(>\)|\(<\)|\(=\)|\(_\)|\(\)“, ”X", string)
Я сейчас буду говорить, а вы поправьте неправильные мои соображения
1.И так переменные у нас могут быть с A по Z
2.утверждения чего можо разделяются таким образом |
3.вы определили все знаки что они должны быть между переменными, и отрицание только с 1 переменной
4.вы раставили скобки по обоим частям со стороны переменных, и отдельно с опрератором НЕ
5. Вы гений

А теперь вопросы

1.я не понял назначение косой черты, я читал тут http://ru.wikipedia.org/wiki/Регулярное_выражение но всёравно не сильно догнал. ОНа както заставляет думать что символ после неё функция?
2.назначение Икса, поидее функция re. будет перебирать “Х” с выражением. Или просто “Х” обозначает выполнение всех поставленых ранее условий?
3.каким образом тут реализовано что вместо А-Z может стоять другая функция?

И теперь по reducE.
почему эта функция выполняется хотя она до этого не задана?
и вобще толком что она делает?
knkd
Alex_Kutsan
2.утверждения чего можо разделяются таким образом |
Да. “|” переводится как “ИЛИ”.

Alex_Kutsan
1.я не понял назначение косой черты, я читал тут http://ru.wikipedia.org/wiki/Регулярное_выражение но всёравно не сильно догнал. ОНа както заставляет думать что символ после неё функция?
Он просто экранирует скобку. Без него скобка является управляющим символом (в языке регулярных выражовываний)

Alex_Kutsan
И теперь по reducE.
почему эта функция выполняется хотя она до этого не задана?
Как это не задана?
def reducE(string):
Alex_Kutsan
2.назначение Икса, поидее функция re. будет перебирать “Х” с выражением.
Это модификатор. Он позволяет игнорировать пробелы в регулярном выражении.
Ed
knkd
Alex_Kutsan
2.назначение Икса, поидее функция re. будет перебирать “Х” с выражением.
Это модификатор. Он позволяет игнорировать пробелы в регулярном выражении.
Это не модификатор, а просто символ, на который заменяется то, что матчится. Он же и переменная в нашем понимании, поскольку входит в диапазон A-Z.
Alex_Kutsan
Ага, вроде уже почти всё прояснилось… функция re. невероятно действена, мне она очень понравилась.
Да, и по делу
Тоесть при прохождении функции re.sub он фактически заменяет любую переменную что входить на Х , или в общем случае всё что входит в на Х.Или всётаки ставит в соответствие с Х любую последоваетльность из ранее перечисленых утверждений?

И вот ещё, всётаки , как ему вы обьяснили что вместо любого из можно вставлять справедливые выражения.
вот этим способом?
def reducE(string):
result = re.sub("\(&[A-Z]\)|\([A-Z]>[A-Z]\)|\([A-Z]<[A-Z]\)|\([A-Z]=[A-Z]\)|\([A-Z]_[A-Z]\)|\([A-Z]\)", "X", string)
if result != string:
return reducE(result)
но тогда у меня есть ещё 1 обьяснение фушкции re.sub
Она выбирает каждое из предложеных выражений( наскоко я ещё понял,вы порядком выражений задали приоитет символов) ищет в string а на найдя заменяет.
ИлИ. она заменяет все выражения, найденые в string.

А потом вы просто от получившегося снова берёте re.sub и и пока оно не станет равным стринг.
А за Х она тогда принимает любое правильное расположение из заданых выражений
knkd
Ed
Это не модификатор, а просто символ, на который заменяется то, что матчится.
Ой :)
Alex_Kutsan
А что означает Мачится.В докуменаци оно посто янно используется но не расказывается что это значит.
Если на него заменяется эт ото что мачится то наверно на него заменяется string
но тогда очему не пашет такой код?
>>> def is_prop_formula(string):
def reducE(string):
result = re.sub("\(&[A-z]\)|\([A-z]>[A-z]\)|\([A-z]<[A-z]\)|\([A-z]=[A-z]\)|\([A-z]_[A-z]\)|\([A-z]\)", string)
if result != string:
return reducE(result)
return result
return reducE(string) == string

>>> is_prop_formula("(&d)")
Traceback (most recent call last):
File "<pyshell#47>", line 1, in <module>
is_prop_formula("(&d)")
File "<pyshell#46>", line 7, in is_prop_formula
return reducE(string) == string
File "<pyshell#46>", line 3, in reducE
result = re.sub("\(&[A-z]\)|\([A-z]>[A-z]\)|\([A-z]<[A-z]\)|\([A-z]=[A-z]\)|\([A-z]_[A-z]\)|\([A-z]\)", string)
TypeError: sub() takes at least 3 arguments (2 given)
и как на него может заменятся если Х это строка а не переменная.
Но вот такой код тоже не пашет
def is_prop_formula(string):
def reducE(string):
result = re.sub("\(&[A-z]\)|\([A-z]>[A-z]\)|\([A-z]<[A-z]\)|\([A-z]=[A-z]\)|\([A-z]_[A-z]\)|\([A-z]\)",A, string)
if result != string:
return reducE(result)
return result
return reducE(string) == A

>>> is_prop_formula("(&d)")
Traceback (most recent call last):
File "<pyshell#50>", line 1, in <module>
is_prop_formula("(&d)")
File "<pyshell#49>", line 7, in is_prop_formula
return reducE(string) == A
File "<pyshell#49>", line 3, in reducE
result = re.sub("\(&[A-z]\)|\([A-z]>[A-z]\)|\([A-z]<[A-z]\)|\([A-z]=[A-z]\)|\([A-z]_[A-z]\)|\([A-z]\)",A, string)
NameError: global name 'A' is not defined
Так на этот Х может заменяется каждый вариант выражения из этого "\(&\)|\(>\)|\(<\)|\(=\)|\(_\)|\(\)"?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB