Задать вопрос
Ответы пользователя по тегу Python
  • Как сделать чтобы python игнорировал символ '%' в строке?

    adugin
    @adugin Куратор тега Python
    >>> s = 'abc%123'
    >>> s
    'abc%123'
    >>> s = 'abc%%12%s3' % 4
    >>> s
    'abc%1243'
    Ответ написан
    Комментировать
  • Поиск комбинаций в строке где один символ играет роль универсального?

    adugin
    @adugin Куратор тега Python
    def checksum(code, awards={'A': 15, 'B': 20, 'C': 30, '': 40}, joker='D'):
        return sum(
            awards.get(''.join(set(triplet)-{joker}), 0) for triplet in zip(*[iter(code)]*3)
        )
    
    checksum('ABCAABDCA')  # 0
    checksum('ADAAABDCA')  # 15

    Или так, например:
    def checksum2(code, awards={'A': 15, 'B': 20, 'C': 30, '': 40}, joker='D'):
        return reduce(
            lambda xsum, triplet: xsum + awards.get(
                ''.join(set(triplet).difference(joker)), 0
            ),
            (code[0:3], code[3:6], code[6:9]), 0
        )
    Ответ написан
    5 комментариев
  • Почему ошибка при перемотке музыки?

    adugin
    @adugin Куратор тега Python
    Комментировать
  • Как настроить кодировку при сохранении html файла в urllib (python 3.4)?

    adugin
    @adugin Куратор тега Python
    1) Какая кодировка прописана в заголовках meta самой страницы, и также о какой кодировке сообщает сервер?
    2) В какую кодировку всё это сохраняется, и соответствует ли кодировка в meta фактической кодировке?

    Технически просто - если, скажем, страница в utf-8, а надо сохранить в cp1251:
    html = urllib.request.urlopen(url).read().decode('utf-8').encode('cp1251')

    ... и проверить кодировку в meta-заголовке сохранённой страницы.

    str(html) - лишнее, html и так строка.
    Ответ написан
    6 комментариев
  • Что такое "Unhashable type"?

    adugin
    @adugin Куратор тега Python
    audio = (
        {'lyrics_id': 3586866, 'title': 'Fruhling in Paris', 'id': 358450897, 'artist': 'Rammstein', 'owner_id': 358450897},
        {'lyrics_id': 3655472, 'title': 'Zwitter', 'id': 358450894, 'artist': 'Rammstein', 'owner_id': 358450897},
    )
    
    keys_to_delete = {'owner_id', 'duration', 'url', 'lyrics_id', 'album_id', 'genre_id'}
    
    for track in audio:
        for attribute in keys_to_delete:
            try:
                del track[attribute]
            except KeyError:
                pass


    Комментарии:
    1) Блок try..except используется для того, чтобы не проверять наличие ключа в словаре дважды (при явной проверке и во время del). Поскольку, вероятно, в большинстве случаев искомые ключи присутствуют, это будет самым быстрым способом.
    2) Про проверку "key in dictionary уже сказал Pavel Denisov.
    Ответ написан
    1 комментарий
  • Как уменьшить функцию?

    adugin
    @adugin Куратор тега Python
    Не очень ясна цель этой манипуляции.

    Если ID - immutable, вы ведь понимаете, что снаружи функции ничего не изменится?
    >>> def foo(**kwargs):
    	kwargs['id'] = 1
    	print 'Internal: %s' % kwargs['id']
    
    >>> d = {'id': 0}
    >>> foo(**d)
    Internal: 1
    >>> d
    {'id': 0}

    И пример изменения снаружи:
    >>> def foo(**kwargs):
    	kwargs['id'][:] = [4, 5, 6]
    	print 'Internal: %s' % kwargs['id']
    	
    >>> d = {'id': [1, 2, 3]}
    >>> foo(**d)
    Internal: [4, 5, 6]
    >>> d
    {'id': [4, 5, 6]}
    Ответ написан
  • Как повысить эффективность кода? Или такое поведение программы считается нормальным?

    adugin
    @adugin Куратор тега Python
    Наиболее быстрый алгоритм:
    from random import random
    
    while True:
        try:
            total = int(raw_input('\nВведите количество бросков: '))
        except ValueError:
            print 'Введено некорректное значение: ожидается целое число.'
        else:
            # side1 = sum(random() < 0.5 for n in xrange(total))
            side1 = int(round(sum(random() for n in xrange(total))))  # эквивалент random() >= 0.5
            side2 = max(0, total) - side1
            print 'Результат: орёл - {0}, решка - {1}'.format(side1, side2)
        finally:
            if raw_input('\nПопробовать ещё раз (Y)? ').upper() != 'Y':
                break

    Ещё вариант:
    import collections, random
    
    options = ('орёл', 'решка')
    
    while True:
        stats = collections.Counter(dict.fromkeys(options, 0))
        try:
            stats.update(
                random.choice(options) for test in xrange(
                    input('\nВведите количество бросков: ')
                )
            )
        except:
            print 'Введено некорректное значение: ожидается целое число.'
        else:
            print 'Результат: {0} - {{{0}}}, {1} - {{{1}}}'.format(*options).format(**stats)
        finally:
            if raw_input('\nПопробовать ещё раз (Y)? ').upper() != 'Y':
                break

    Замеры скорости:
    >>> timeit('choice((0,1))', setup='from random import random, choice', number=10**6)
    1.4363103769230747
    >>> timeit('random() < 0.5', setup='from random import random, choice', number=10**6)
    0.18878976080804932

    0) Вас не смущает, что Вы используете заведомо равномерное (uniform) распределение, о котором говорится во вступительном абзаце к модулю random?
    1) Про русский язык уже написали. Кроме того, зачем смешивать английские слова (times) с транслитом (monetka)? Пишите всё на английском.
    2) input() уже конвертирует значение из строки. Если число нецелое (float), то int() отработает без ошибок: int(3.14) = 3
    3) Странная структура программы. Не надо делать вложенную структуру (почему цикл бросков монеты идёт под else?), используйте break и continue, чтобы код был более плоским. "Плоское лучше, чем вложенное".
    4) В цикле броско монеты операторы "count += 1" и "times -= 1" следует вынести из блока if..elif, чтобы не дублировать оди и тот же код, который всё равно должен выполниться.
    5) Если не выпал орёл, то проверять условие var == 'решка' не нужно, достаточно простого else. Там кроме решки больше ничего быть не может.
    6) Какая версия Python? 2.x или 3.x? Про целочисленное деление помните?
    7) Дальше у меня сломался моск...
    Ответ написан
    7 комментариев
  • Как определить тип числа с помощью regexp?

    adugin
    @adugin Куратор тега Python
    def convert(x):
        for func in (int, float, complex):
            try:
                return func(x)
            except ValueError:
                pass
        return float('NaN')
    Ответ написан
    Комментировать
  • Как, имея только строку вида: "X", программно создать переменную с именем равным содержимому строки?

    adugin
    @adugin Куратор тега Python
    >>> exec('xyz="xyz"')
    >>> xyz
    'xyz'
    >>> exec('{s}="{s}"'.format(s='xyz'))
    >>> xyz
    'xyz'

    UPD Ещё: https://github.com/brennerm/PyTricks/blob/master/s...
    Ответ написан
    Комментировать
  • Как разбить строку на подстроки?

    adugin
    @adugin Куратор тега Python
    >>> s = '123456789'
    >>> from textwrap import wrap
    >>> wrap(s, 3)
    ['123', '456', '789']
    >>> map(''.join, zip(*[iter(s)]*3))
    ['123', '456', '789']
    Ответ написан
    Комментировать
  • Как ускорить регулярные выражения в python?

    adugin
    @adugin Куратор тега Python
    Нужно увеличить кэш:
    >>> import re
    >>> re._MAXCACHE
    100
    >>> re._MAXCACHE = 3000
    >>> re._MAXCACHE
    3000

    Подозреваю, что при этом re.compile() в явном виде использовать не обязательно.
    Ответ написан
    Комментировать
  • Как склеить переменные в строку в python?

    adugin
    @adugin Куратор тега Python
    Используйте join():
    >>> from timeit import timeit
    >>> def f1(s1='foo', s2='bar'):
    	return ' - '.join((s1, s2))
    
    >>> f1()
    'foo - bar'
    >>> def f2(s1='foo', s2='bar'):
    	return '{0} - {1}'.format(s1, s2)
    
    >>> f2()
    'foo - bar'
    >>> def f3(s1='foo', s2='bar'):
    	return '%s - %s' % (s1, s2)
    
    >>> f3()
    'foo - bar'
    >>> timeit(f1)
    0.7238124336211288
    >>> timeit(f2)
    1.3038862714413124
    >>> timeit(f3)
    0.8215918286469828
    Ответ написан
    Комментировать
  • Как организовать обработку поля namedtuple при [первом] вызове?

    adugin
    @adugin Автор вопроса, куратор тега Python
    Пока удалось родить такое кривенькое решение. При каждом обращении атрибут пересчитывается заново. Хорошо бы добавить memoization. Но, по крайней мере, работает:
    >>> def namedtuplex(*args, **kwargs):
        def getitem(self, key):
            if type(key) is str:
                value = getattr(self, key)
            else:
                value = tuple.__getitem__(self, key)
            if type(value) is str:
                value = value.strip('"')
                try:
                    value = eval(value)
                except:
                    value = intern(value)
            return value
        ntuple = collections.namedtuple(*args, **kwargs)
        ntuple.__getitem__ = getitem
        return ntuple
    
    >>> XDR = namedtuplex('XDR', 'a b c d e f g')
    >>> xdr = XDR('"abc"', 'def', '5', '"3.14"', 2.71, [1,2], None)
    >>> xdr.a
    'abc'
    >>> xdr.b
    'def'
    >>> xdr.c
    5
    >>> xdr.d
    3.14
    >>> xdr.e
    2.71
    >>> xdr.f
    [1, 2]
    >>> xdr.g
    >>> xdr['a']
    'abc'
    >>> xdr['b']
    'def'
    >>> xdr['c']
    5
    >>> xdr['d']
    3.14
    >>> xdr['e']
    2.71
    >>> xdr['f']
    [1, 2]
    >>> xdr['g']
    >>>
    В зависимость от конкретного применения можно сделать что-то такое:
    eval(value.strip('"'))
    Либо разбирать непосредственно через int() и float() в блоках try..except.
    Ответ написан
    Комментировать
  • Как инвертировать словарь без использования дополнительной памяти?

    adugin
    @adugin Автор вопроса, куратор тега Python
    Пока додумался до такого метода:
    xcache = dict()
    while cache:
        	key, val = cache.iteritems().next()
        	xcache[cache.pop(key)] = key
    Такой способ в 3 раза величивает время исполнения скрипта (с 60 до 180 секунд на моём ноутбуке) по сравнению с традиционным методом инвертирования "в лоб". Есть ли способ лучше?

    Update #1: Тоже тормозит.
    xcache = dict()
    cpop = cache.pop
    while cache:
        key = cache.iterkeys().next()
        xcache[cpop(key)] = key
    del cache

    Update #2: Вот так скорость вернулась на значение 60 секунд. Что ещё?
    xcache = dict()
    cpop = cache.popitem
    while cache:
        key, val = cpop()
        xcache[val] = key
    del cache
    Ответ написан
    Комментировать
  • С чем сравнить число в python, чтобы в результате всегда было true/false?

    adugin
    @adugin Куратор тега Python
    >>> float('inf')
    inf
    >>> float('-inf')
    -inf
    >>> -float('inf')
    -inf
    >>> infinity = float('inf')
    >>> 42 < infinity
    True
    Ответ написан
    Комментировать
  • Как определить наименьшее уникальное значение в словаре?

    adugin
    @adugin Куратор тега Python
    Самое простое и эффективное решение без лишних действий:
    from collections import Counter
    
    def min_unique(dictionary):
        minval, result = float('inf'), None
        counter = Counter(dictionary.itervalues())
        for key, val in dictionary.iteritems():
            if (val < minval) and (counter[val] == 1):
                minval = val
                result = (key, val)
        return result
    
    data = {'a': 23, 'b': 26, 'c': 45, 'd': 23}
    print min_unique(data)

    Или так:
    from operator import itemgetter
    from itertools import ifilter
    
    def min_unique(dictionary):
        inverted = dict()
        for key, value in dictionary.iteritems():
            inverted[value] = None if value in inverted else key
        filtered = ifilter(itemgetter(1), inverted.iteritems())
        try:
            value, key = min(filtered, key=itemgetter(0))
        except ValueError:
            value, key = None, None
        return key, value

    Ещё интересный вариант с итераторами (узкое место - сортировка):
    from operator import itemgetter
    from itertools import groupby
    
    def min_unique(dictionary, ig=itemgetter(1)):
        grouped = groupby(sorted(dictionary.viewitems(), key=ig), key=ig)
        for key, entries in grouped:
            entry = entries.next()
            try:
                entries.next()
            except StopIteration:
                return entry
            else:
                continue
    Ответ написан
    2 комментария
  • Как на Python'е сделать так, чтобы программа сама могла создавать переменные, списки, кортежи и т.д.?

    adugin
    @adugin Куратор тега Python
    exec()
    eval()
    также посмотрите в исходники класса namedtuple модуля collections
    >>> exec('a = [1,2,3]')
    >>> a
    [1, 2, 3]
    Ответ написан
    Комментировать
  • Есть ли способ автоматически выставлять отступы в python?

    adugin
    @adugin Куратор тега Python
    А нечего в Notepad писать :) Используйте IDE или хотя бы Notepad++
    Ответ написан
  • Работа с анаграммами, как можно оптимизировать скрипт?

    adugin
    @adugin Куратор тега Python
    Расчёт анаграмм (permutations) здесь не требуется (пп. 2 и 3 - вводят в заблуждение).
    Поэтому скорость выполнения представленного ниже кода не зависит от длины слова.
    На базе в 20.000 слов выполняется мгновенно даже с 'antidisestablishmentarianism':
    from collections import Counter
    from itertools import ifilter
    
    def criteria(dictword):
        return (
            wlen == len(dictword) and
            wset == set(dictword) and
            wcnt == Counter(dictword)
        )
    
    while True:
    
        word = raw_input('\nEnter word: ')
        wlen, wset, wcnt = len(word), set(word), Counter(word)
    
        with open('thesaurus.txt') as f:
            thesaurus = (line.rstrip() for line in f)
            for dictword in ifilter(criteria, thesaurus):
                print dictword
    
        if word in {'exit', 'quit'}:
            break
    Ответ написан
    Комментировать
  • Как написать простую программу вычисления квадратных уравнений на Python?

    adugin
    @adugin Куратор тега Python
    1) Надо использовать float(), а не int()
    2) Конструкция 'from __future__ import division' тоже может пригодиться.

    >>> from math import sqrt
    >>> def solver():
        try:
            a, b, c = map(float, raw_input('Введите a, b, c через пробел: ').split())
        except:
            print 'На колу мочало - начинай сначала!'
        else:
            d = b*b - 4*a*c
            if d >= 0:
                sd = sqrt(d)
                root = lambda k: '{:.6f}'.format((-b+k*sd)/(2*a))
                solution = ' и '.join(set(map(root, (-1,1))))
            else:
                solution = 'уравнение не имеет решений'
            print 'Ответ: %s' % solution
    
    >>> solver()
    Введите a, b, c через пробел: 1, 2 3
    На колу мочало - начинай сначала!
    >>> solver()
    Введите a, b, c через пробел: 1 2 3
    Ответ: уравнение не имеет решений
    >>> solver()
    Введите a, b, c через пробел: 4 9 1
    Ответ: -0.117218 и -2.132782
    >>>
    Ответ написан
    Комментировать