Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 25, 2017 11:56:59

endless_lama
Зарегистрирован: 2017-11-24
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Dive into python не понятно

py.user.next, огромное спасибо за пояснение! Теперь намного понятнее.

Но у меня еще пара вопросов…

1. Что конкретно делает вот эта строка? Я понимаю, что это очень похоже на первый вопрос в этом треде, но я туплю… Я понимаю, что к self.cache_index мы обращаемся только если нужно нужного правила нет в cache, но почему тут “минус 1”?

 return self.cache[self.cache_index - 1]

2. Далее по коду:

 def build_match_and_apply_functions(pattern, search, replace):
     def matches_rule(word):
        return re.search(pattern, word)
     def apply_rule(word):
        return re.sub(search, replace, word)
     return (matches_rule, apply_rule)
def plural(noun):
      for matches_rule, apply_rule in rules:
         if matches_rule(noun):
            return apply_rule(noun)
      raise ValueError('no matching rule for {0}'.format(noun))

Почему в одном случае matches_rule(word), а ниже - matches_rule(noun)? Разве атрибуты не должны одинаково в данном случае называться?

Отредактировано endless_lama (Ноя. 25, 2017 11:58:20)

Офлайн

#2 Ноя. 25, 2017 14:40:13

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

Dive into python не понятно

endless_lama
Что конкретно делает вот эта строка?
Если у нас есть заполненный кеш и мы начали итератор заново перебирать, то нам надо вернуть первое правило из кеша. При этом нужно запомнить, что первое правило прочитано, чтобы при следующем чтении бралось уже второе правило. Но так как мы первое правило сразу же должны вернуть из функции __next__(), то мы не сможем после возврата из функции переставить индекс кеша внутри функции. Поэтому индекс переставляется до возврата из функции, а во время возврата из функции просто берётся предыдущее значение индекса. Тогда мы выходим и у нас как первое правило вернулось из кеша, так и индекс кеша переставлен на второе правило. При следующем чтении кеша будет читаться второе правило и индекс кеша будет указывать на третье правило.

endless_lama
Почему в одном случае matches_rule(word), а ниже - matches_rule(noun)?
Потому что в одном случае это определение функции, а в другому случае это вызов функции.

endless_lama
Разве атрибуты не должны одинаково в данном случае называться?
Это не атрибуты, а аргументы функции. Аргументы функции (или параметры функции) бывают формальными и бывают фактическими. Формальный параметр - это параметр в определении функции. Фактический параметр - это параметр в вызове функции.

В определении функции ты можешь придумать любое имя формального параметра
  
def matches_rule(word):
В вызове функции ты можешь передавать любой фактический параметр
  
if matches_rule(noun):
  
if matches_rule('abc'):
При вызове функции значение фактического параметра привязывается к формальному параметру и уже под этим формальным параметром используется внутри функции.

Вот пример
  
>>> def f(n):
...   return n * n
... 
>>> f(3)
9
>>> f(5)
25
>>> x = 4
>>> f(x)
16
>>>
n - это формальный параметр функции f()
3 - фактический параметр вызова функции f()
5 - фактический параметр вызова функции f()
x - фактический параметр вызова функции f()



Отредактировано py.user.next (Ноя. 25, 2017 15:10:32)

Офлайн

#3 Ноя. 26, 2017 09:05:47

endless_lama
Зарегистрирован: 2017-11-24
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Dive into python не понятно

py.user.next, большое спасибо за объяснения, теперь все намного понятнее! Думаю, в будущем еще не раз буду к Вам обращаться. Может, посоветуете какой-нибудь хороший понятный учебник по Python?

Офлайн

#4 Дек. 1, 2017 16:14:22

endless_lama
Зарегистрирован: 2017-11-24
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Dive into python не понятно

Дальше идет глава про криптарифмы, где рассматривается вот этот код:

 import re
import itertools
def solve(puzzle):
    words = re.findall('[A-Z]+', puzzle.upper())
    unique_characters = set(''.join(words))
    assert len(unique_characters) <= 10, 'Too many letters'
    first_letters = {word[0] for word in words}
    n = len(first_letters)
    sorted_characters = ''.join(first_letters) + \
        ''.join(unique_characters - first_letters)
    characters = tuple(ord(c) for c in sorted_characters)
    digits = tuple(ord(c) for c in '0123456789')
    zero = digits[0]
    for guess in itertools.permutations(digits, len(characters)):
        if zero not in guess[:n]:
            equation = puzzle.translate(dict(zip(characters, guess)))
            if eval(equation):
                return equation
if __name__ == '__main__':
    import sys
    for puzzle in sys.argv[1:]:
        print(puzzle)
        solution = solve(puzzle)
        if solution:
            print(solution)

Вроде все понятно, кроме:

 first_letters = {word[0] for word in words}
n = len(first_letters)
sorted_characters = ''.join(first_letters) + \
    ''.join(unique_characters - first_letters)

Зачем нужны эти first_letters и их длина, если есть уже unique_characters, куда эти first_letters уже входят?

Офлайн

#5 Дек. 2, 2017 02:44:11

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

Dive into python не понятно

endless_lama
Вроде все понятно, кроме:
Первые буквы слов не могут быть нулями. Поэтому он их выносит и складывает в одно место. А потом берёт все размещения (а их дофига) и отбрасывает те из них, которые точно не подойдут, потому что они попадают на нули. А оставшиеся размещения, которые могут подойти, он проверяет уже через вычисление уравнения.

Пример:
ABC + BCD = CDE

Первые буквы слов не могут быть нулями
A, B, C

Тогда он получает все размещения (изобразим построчно)
(A, B, C, D, E), (A, B, C, E, D), (A, B, E, C, D), …
(B, A, C, D, E), (B, A, C, E, D), (B, A, E, C, D), …
(E, A, B, C, D), (E, A, B, D, C), (E, A, D, B, C), …

там их ещё дофига (5! = 120)

И тут мы видим, что A и B не могут быть нулями, поэтому первые две строки со всеми размещениями мы можем просто выкинуть, потому что A и B стоят в них на месте нуля. То есть мы их выкидываем, не подставляем в уравнение, не пытаемся его вычислить. Экономим время значительно.

А третью строку мы можем брать, потому что на месте нуля там E стоит. А E в исходном уравнении первой буквой не является и поэтому вполне может быть нулём.




Отредактировано py.user.next (Дек. 2, 2017 02:46:46)

Офлайн

#6 Дек. 2, 2017 16:48:15

endless_lama
Зарегистрирован: 2017-11-24
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Dive into python не понятно

py.user.next
Первые буквы слов не могут быть нулями.

Теперь понятно, огромное спасибо!!
А зачем нужно все переводить в ascii?
 characters = tuple(ord(c) for c in sorted_characters)
digits = tuple(ord(c) for c in '0123456789')

а… то есть если мы их не переведем в ascii, translate() не будет работать, так?

 equation = puzzle.translate(dict(zip(characters, guess)))

Отредактировано endless_lama (Дек. 3, 2017 09:45:09)

Офлайн

#7 Дек. 20, 2017 08:06:24

endless_lama
Зарегистрирован: 2017-11-24
Сообщения: 7
Репутация: +  0  -
Профиль   Отправить e-mail  

Dive into python не понятно

Далее автор создает две функции:

Первая преобразует числа в Римские числа:

 roman_numeral_map = (('M',  1000),
                     ('CM', 900),
                     ('D',  500),
                     ('CD', 400),
                     ('C',  100),
                     ('XC', 90),
                     ('L', 50),
                     ('XL', 40),
                     ('X', 10),
                     ('IX', 9),
                     ('V', 5),
                     ('IV', 4),
                     ('I', 1))
def to_roman(n):
    '''converts integers to Roman numerals'''
    if not (0 < n < 4000):
        raise OutOfRangeError('Number out of range (must be 1...3999)')
    if not isinstance(n, int):
        raise NotIntegerError('non-integers cannot be converted')
    result = ''
    for numeral, integer in roman_numeral_map:
        while n >= integer:
            result += numeral
            n -=integer
    return result

Вторая функция, наоборот, переводит Римские числа в обычные:

 def from_roman(s):
    '''converts Roman numerals to integers'''
    result = 0
    index = 0
    for numeral, integer in roman_numeral_map:
        while s[index:index+len(numeral)] == numeral:
            result += integer
            index += len(numeral)
    return result

И вот здесь непонятно назначение index (почему в первой функции он не нужен?) и вот эта строка:

 index:index+len(numeral)

Заранее спасибо!

Отредактировано endless_lama (Дек. 20, 2017 08:13:42)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version