Как работи тази програма?

Попаднах на този код, който съвпада със заместващия знак * срещу низ. * може да се счита за 0 или повече символа.

def samePattern(main,pattern):
    if pattern=="*" or main==pattern:
        return True
    if main=="":
        return False
    if main[0:1]==pattern[0:1]:
        return samePattern(main[1:],pattern[1:])

    if pattern[0:1]=="*":
        return samePattern(main[1:],pattern) or samePattern(main,pattern[1:])

    return False

Въпреки че мисля, че разбрах основните случаи, не разбирам как линията

if pattern[0:1]=="*":
        return samePattern(main[1:],pattern) or samePattern(main,pattern[1:])

работи.

Може ли някой да обясни как работи?


person Community    schedule 02.10.2015    source източник


Отговори (3)


Важният момент е къде е заместващият знак:

  • test*
  • te*ing
  • *ing

В първия случай, със заместващия знак в края, testing and test*:

def samePattern(main,pattern):
    if pattern=="*" or main==pattern:                  #  3.
        return True                                    
    if main=="":                                       #  4.
        return False                                   
   if main[0:1]==pattern[0:1]:                         #  1.
       return samePattern(main[1:],pattern[1:])        #

    if pattern[0:1]=="*":
        return samePattern(main[1:],pattern) or samePattern(main,pattern[1:])
                            ^                       ^
                            | # 2.                  | # 5.

    return False

Секция 1. обикаля както текста, така и шаблона за test, докато шаблонът стигне до заместващия знак и те вече не са един и същ знак.

Секция 2. задейства и измества само текста по един знак и опитва отново.

Секция 3. попадне, моделът е единичен '*' без нищо друго и връща True.

Секция 2. се връща със стойността True, оценката на късо съединение на Python не тества другата страна на or, защото не е необходимо, и цялото нещо се срива до True успешно съвпадение.


Вторият случай, със заместващия знак в средата, започва по същия начин. testing and te*ing:

Секция 1. обхожда текста и шаблона, докато моделът стигне до заместващия знак.

Сега текстът и моделът са sting and *ing, което е същото като третия случай - заместващ знак отпред.


Третият случай със заместващия знак отпред, напр. testing and *ing:

Раздел 2. се задейства, защото моделът започва с *. (Пропуска раздел 3, защото не е само звезда). Секция 2 премества един текстов знак и опитва отново със същия модел.

Същото се случва отново и отново, докато се задейства Раздел 4. и текстът изтече. Сега това връща False.

Сега първият False се върна от лявата част на теста or, дясната част се опитва за първи път. Това измества шаблона след заместващия знак, *ing става ing.

Но все още сме дълбоко в рекурсията, при последния знак от текста - g and ing, който връща False от Раздел 1.

И двете страни на теста or на тази дълбочина върнаха False, така че целият ред го прави.

Това се връща на ниво нагоре и се опитва другата страна на or теста на това ниво. ng and ing. Невярно от раздел 1.

И двете страни на теста or на тази дълбочина върнаха False, така че целият ред го прави.

Това се връща на ниво нагоре и се опитва другата страна на or теста на това ниво. ing and ing. Вярно от раздел 3 и main==pattern.

Това връща True, or връща True и всичко се срива в купчина True.


Всички части работят заедно, но грубо казано, Раздел 1. съпоставя текст с текст, Раздели 2 и 3 съвпадат с крайни заместващи знаци, а Раздели 4 и 5 съвпадат с начални заместващи знаци и те се припокриват, което се грижи за заместващите знаци в средата.


Добавяне на някои printf отстраняване на грешки помогна ми да видя какво се случва:

първи

def samePattern(main,pattern):
    print "main", main, "pattern", pattern

[..]

тогава

    if pattern[0:1]=="*":
        x = samePattern(main[1:],pattern)
        print "x", x
        return x or samePattern(main,pattern[1:])
person TessellatingHeckler    schedule 02.10.2015

if pattern[0:1]=="*":

Изявлението по-горе означава, че когато символът на променливата на модела при индекс 0 е '*', тогава условието е вярно и след това се изпълнява под условното изявление

връщане на същия шаблон(основен[1:],модел) или същия шаблон(основен,модел[1:])

Този оператор извиква функцията "samePattern" рекурсивно и предава параметри като (стойност на основната променлива, започваща от индекс от 1 до n-1 знака, променлива на шаблон)

person Community    schedule 02.10.2015

'*' съответства на 0 или повече знаци. Последният израз if казва: ако pattern е във формата '*' + p, тогава върнете True, ако:

  • всичко след първия знак на main съвпада с шаблон (така че '*' в началото на pattern потенциално ще съвпада с повече знаци от началото на main), или
  • p, опашката на pattern, съвпада с main (приключихме с '*')
person BrianO    schedule 02.10.2015
comment
[0] се проваля на празен низ, където частта е просто празна, може би затова оригиналният автор го е използвал. - person jonrsharpe; 02.10.2015
comment
@jonrsharpe Да, прав си. Изтрих прибързаната лъжа. Въпреки това изглежда, че една проста промяна позволява замяната на [0:1] с [0]: променете второто if на if main == '' or pattern == '': return False. Ако този ред бъде достигнат, предишното if е неуспешно, така че main не е равно на pattern; и вероятно искаме да върнем False, ако main не е празно, но pattern е. С тази промяна, ако първите две ifs се провалят, тогава и main и pattern не са празни. - person BrianO; 02.10.2015