Найти - Пользователи
Полная версия: Замена значений в последовательности пар
Начало » Python для новичков » Замена значений в последовательности пар
1 2
reclosedev
Кстати, в случае с ' '.join() список будет немного эффективнее по времени и по памяти чем генератор, потому что join'у требуется два прохода.

Более развернутый ответ от Раймонда Хеттинжера на StackOverflow
Андрей Светлов

pyuser, а не желаешь ли сделать патч в 3.3, чтобы OrderedDict был не таким медленным?

pyuser
Андрей Светлов так в инете лежит не одна реализация, которая работает быстрее OrderedDict (имеется ввиду python 3.2 и метод update)
для себя я наваял следующий велосипед (слегка поправил библиотечный код):
from collections import deque, ItemsView, KeysView, ValuesView
from itertools import tee
from reprlib import recursive_repr as _recursive_repr
class OrderedDict(dict):
    'Dictionary that remembers insertion order'
    def __init__(self, *args):
        '''Initialize an ordered dictionary.  The signature is the same as
        regular dictionaries, but keyword arguments are not recommended because
        their insertion order is arbitrary.
        '''
        if len(args) > 1:
            raise TypeError('expected at most 1 arguments, got %d' % len(args))
        super().__init__()
        if not hasattr(self, '_keys'):
            self._keys = deque()
        self.update(*args)
    def __setitem__(self, key, value):
        'od.__setitem__(i, y) <==> od[i]=y'
        if key not in self:
            self._keys.append(key)
        super().__setitem__(key, value)
    def __delitem__(self, key):
        'od.__delitem__(y) <==> del od[y]'
        self._keys.remove(key)
        super().__delitem__(key)
    def __iter__(self):
        'od.__iter__() <==> iter(od)'
        return iter(self._keys)
    def __reversed__(self):
        'od.__reversed__() <==> reversed(od)'
        return reversed(self.__key)
    def clear(self):
        'od.clear() -> None.  Remove all items from od.'
        self._keys.clear()
        super().clear()
    def popitem(self, last=True):
        '''od.popitem() -> (k, v), return and remove a (key, value) pair.
        Pairs are returned in LIFO order if last is true or FIFO order if false.
        '''
        if not self:
            raise KeyError('dictionary is empty')
        key = self._keys.pop() if last else self._keys.popleft()
        value = super().pop(key)
        return key, value
    def move_to_end(self, key, last=True):
        '''Move an existing element to the end (or beginning if last==False).
        Raises KeyError if the element does not exist.
        When last=True, acts like a fast version of self[key]=self.pop(key).
        '''
        self._keys.remove(key)
        if last:
            self._keys.append(key)
        else:
            self._keys.appendleft(key)
    def __sizeof__(self):
        sizeof = _sys.getsizeof
        return sizeof(self._keys) + sizeof(self)
    def update(self, *args):
        if not args:
            raise TypeError("update() takes at least 1 argument (0 given)")
        args = args[0]
        tmp = set(self)
        if hasattr(args, "keys"):
            for k in args.keys():
                if k not in tmp:
                    tmp.add(k)
                    self._keys.append(k)
        else:
            args, a = tee(args)
            for k, _ in a:
                if k not in tmp:
                    tmp.add(k)
                    self._keys.append(k)
        super().update(args)
    def keys(self):
        return KeysView(self)
    def items(self):
        return ItemsView(self)
    def values(self):
        return ValuesView(self)
    __marker = object()
    def pop(self, key, default=__marker):
        '''od.pop(k[,d]) -> v, remove specified key and return the corresponding
        value.  If key is not found, d is returned if given, otherwise KeyError
        is raised.
        '''
        if key in self:
            self._keys.remove(key)
            return super().pop(key)
        if default is self.__marker:
            raise KeyError(key)
        return default
    def setdefault(self, key, default=None):
        'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
        if key in self:
            return self[key]
        self[key] = default
        return default
    @_recursive_repr()
    def __repr__(self):
        'od.__repr__() <==> repr(od)'
        if not self:
            return '%s()' % (self.__class__.__name__,)
        return '%s(%r)' % (self.__class__.__name__, list(self.items()))
    def __reduce__(self):
        'Return state information for pickling'
        items = [[k, v] for k, v in self.items()]
        inst_dict = vars(self).copy()
        inst_dict.pop('_keys', None)
        return (self.__class__, (items,), inst_dict)
    def copy(self):
        'od.copy() -> a shallow copy of od'
        return self.__class__(self)
    @classmethod
    def fromkeys(cls, iterable, value=None):
        '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
        If not specified, the value defaults to None.
        '''
        self = cls(((k, value) for k in iterable))
        return self
    def __eq__(self, other):
        '''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
        while comparison to a regular mapping is order-insensitive.
        '''
        if isinstance(other, OrderedDict):
            return len(self)==len(other) and \
                   all(p==q for p, q in zip(self.items(), other.items()))
        return super().__eq__(self, other)
    def __ne__(self, other):
        return not (self == other)
по скорости создания и обновления это конечно не встроенный dict :(, тем не менее создание и обновление объектов происходит на 65% быстрее чем те же самые операции с библиотечным классом
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