“” .join (инвертировал (val)) по сравнению с val [::-1] …, который является pythonic?

В качестве примера того, как использовать запоминание для повышения производительности алгоритма, следующий пример выполняется примерно в 300 раз быстрее для этого конкретного теста. Раньше это занимало ~ 200 секунд; 2/3 запомнил.


class Slice:

    __slots__ = 'prefix', 'root', 'suffix'

    def __init__(self, prefix, root, suffix):
        self.prefix = prefix
        self.root = root
        self.suffix = suffix

################################################################################

class Match:

    __slots__ = 'a', 'b', 'prefix', 'suffix', 'value'

    def __init__(self, a, b, prefix, suffix, value):
        self.a = a
        self.b = b
        self.prefix = prefix
        self.suffix = suffix
        self.value = value

################################################################################

class Tree:

    __slots__ = 'nodes', 'index', 'value'

    def __init__(self, nodes, index, value):
        self.nodes = nodes
        self.index = index
        self.value = value

################################################################################

def old_search(a, b):
    # Initialize startup variables.
    nodes, index = [], []
    a_size, b_size = len(a), len(b)
    # Begin to slice the sequences.
    for size in range(min(a_size, b_size), 0, -1):
        for a_addr in range(a_size - size + 1):
            # Slice "a" at address and end.
            a_term = a_addr + size
            a_root = a[a_addr:a_term]
            for b_addr in range(b_size - size + 1):
                # Slice "b" at address and end.
                b_term = b_addr + size
                b_root = b[b_addr:b_term]
                # Find out if slices are equal.
                if a_root == b_root:
                    # Create prefix tree to search.
                    a_pref, b_pref = a[:a_addr], b[:b_addr]
                    p_tree = old_search(a_pref, b_pref)
                    # Create suffix tree to search.
                    a_suff, b_suff = a[a_term:], b[b_term:]
                    s_tree = old_search(a_suff, b_suff)
                    # Make completed slice objects.
                    a_slic = Slice(a_pref, a_root, a_suff)
                    b_slic = Slice(b_pref, b_root, b_suff)
                    # Finish the match calculation.
                    value = size + p_tree.value + s_tree.value
                    match = Match(a_slic, b_slic, p_tree, s_tree, value)
                    # Append results to tree lists.
                    nodes.append(match)
                    index.append(value)
        # Return largest matches found.
        if nodes:
            return Tree(nodes, index, max(index))
    # Give caller null tree object.
    return Tree(nodes, index, 0)

################################################################################

def search(memo, a, b):
    # Initialize startup variables.
    nodes, index = [], []
    a_size, b_size = len(a), len(b)
    # Begin to slice the sequences.
    for size in range(min(a_size, b_size), 0, -1):
        for a_addr in range(a_size - size + 1):
            # Slice "a" at address and end.
            a_term = a_addr + size
            a_root = a[a_addr:a_term]
            for b_addr in range(b_size - size + 1):
                # Slice "b" at address and end.
                b_term = b_addr + size
                b_root = b[b_addr:b_term]
                # Find out if slices are equal.
                if a_root == b_root:
                    # Create prefix tree to search.
                    key = a_pref, b_pref = a[:a_addr], b[:b_addr]
                    if key not in memo:
                        memo[key] = search(memo, a_pref, b_pref)
                    p_tree = memo[key]
                    # Create suffix tree to search.
                    key = a_suff, b_suff = a[a_term:], b[b_term:]
                    if key not in memo:
                        memo[key] = search(memo, a_suff, b_suff)
                    s_tree = memo[key]
                    # Make completed slice objects.
                    a_slic = Slice(a_pref, a_root, a_suff)
                    b_slic = Slice(b_pref, b_root, b_suff)
                    # Finish the match calculation.
                    value = size + p_tree.value + s_tree.value
                    match = Match(a_slic, b_slic, p_tree, s_tree, value)
                    # Append results to tree lists.
                    nodes.append(match)
                    index.append(value)
        # Return largest matches found.
        if nodes:
            return Tree(nodes, index, max(index))
    # Give caller null tree object.
    return Tree(nodes, index, 0)

################################################################################

import time
a = tuple(range(50))
b = (48, 11, 5, 22, 28, 31, 14, 18, 7, 29, 49, 44, 47, 36, 25, 27,
     34, 10, 38, 15, 21, 16, 35, 20, 45, 2, 37, 33, 6, 30, 0, 8, 13,
     43, 32, 1, 40, 26, 24, 42, 39, 9, 12, 17, 46, 4, 23, 3, 19, 41)

start = time.clock()
old_search(a, b)
stop = time.clock()

print('old_search() =', stop - start)

start = time.clock()
search({}, a, b)
stop = time.clock()

print('search() =', stop - start)

Ссылка: Как можно применить запоминание к этому алгоритму?

14
задан SilentGhost 8 November 2009 в 11:38
поделиться

4 ответа

Моя жена Анна прозвала x [:: - 1] «марсианский смайлик» - я в основном кланяюсь ей (и ее многолетнему опыту в тренировках и т. Д., И исследования в области психологии человека и c), когда дело доходит до суждения о том, что легко и естественно для большинства людей, и она абсолютно любит боевой смайлик. «Просто пройдите в обратном направлении» - насколько более прямолинейно и с высокой степенью абстракции, чем подробная спецификация «перевернуть его, а затем присоединить обратно»!

Кроме того, python -mtimeit часто является Хороший судья в том, что такое Pythonic: ведущие питонисты на протяжении многих лет, конечно, стремились оптимизировать то, что им чаще всего требовалось и использовалось, поэтому очень существенная разница в производительности говорит вам, что «соответствует зерну» языка и его лучших практиков.

45
ответ дан 1 December 2019 в 06:21
поделиться

Второй (на мой взгляд) более питонический, поскольку он проще, короче и понятнее.

Для получения дополнительной информации о том, что такое Pythonic , я бы порекомендовал Дзен Питона :

Красивое лучше, чем уродливое.
Явное лучше, чем неявное.
Лучше простое, чем сложное.
Сложное лучше, чем сложное.
Плоский лучше, чем вложенный.
Разреженное лучше плотного.
Важна удобочитаемость.
Особых случаев недостаточно, чтобы нарушать правила.
Хотя практичность важнее чистоты.
Ошибки никогда не должны проходить незаметно.
Если явно не отключен звук.
Перед лицом двусмысленности откажитесь от соблазна угадать.
Должен быть один - а желательно только один - очевидный способ сделай это.
Хотя сначала этот способ может быть не очевиден, если вы не голландец.
Сейчас лучше, чем никогда.
Хотя никогда не бывает лучше, чем прямо сейчас .
Если реализацию трудно объяснить, это плохая идея.
Если реализацию легко объяснить, это может быть хорошей идеей.
Пространства имен - одна отличная идея - давайте сделаем их больше!

На мой взгляд, ваш второй пример удовлетворяет этим принципам:

Красивое лучше, чем уродливое.
Лучше простое, чем сложное.
Лучше разреженное, чем плотное.
Читаемость имеет значение.

4
ответ дан 1 December 2019 в 06:21
поделиться

Для строки, как и у вас, я бы выбрал первый вариант, поскольку он дает понять, что результат, который вам нужен, является строкой. Для списка или другого итеративного / срезаемого я бы выбрал второй.

Дополнительным преимуществом первой формы является то, что она будет работать, если val на самом деле не строка, а какой-то другой итерабельный символы (например, какой-то генератор). В некоторых случаях это имеет большое значение.

0
ответ дан 1 December 2019 в 06:21
поделиться

Во-первых, если вы новичок, не волнуйтесь, что более питонично или нет. Это запах языковых войн, и вы все равно найдете собственное мнение. Просто используйте способ, который, по вашему мнению, более читабелен / проще для вас, и я думаю, вы найдете свет.

Тем не менее, я согласен с отличным ответом Алекса (поскольку он всегда прав), и я бы добавил дополнительный комментарий, почему вам следует предпочесть второй метод - первый будет работать правильно, только если val является строкой.

0
ответ дан 1 December 2019 в 06:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: