В python есть что-то вроде обновленного, то есть для обновления того, что отсортировано для сортировки? - PullRequest
12 голосов
/ 28 февраля 2012

В Python, если я сделаю следующее:

>>> list = [ 3, 2, 1]
>>> sorted_list = k.sort()

Тогда sorted_list равно None и list сортируется:

>>> sorted_list = k.sort()
>>> print list, sorted_list
[1, 2, 3] None

Однако, если я сделаю следующее:

>>> list = [ 3, 2, 1]
>>> sorted_list = sorted(list)

Тогда list остается несортированным, а sorted_list содержит копию отсортированного списка:

>>> print list, sorted_list
[3, 2, 1] [1, 2, 3]

Мне интересно, есть ли эквивалент для функции update для словарей.

Таким образом, я мог бы сделать что-то вроде этого:

def foo(a, b, extra={}):
    bar = { 'first': a, 'second': b }
    special_function(**updated(bar, extra))
    normal_function(**bar)

вместо того, чтобы делать что-то вроде этого:

def foo(a, b, extra={}):
    bar = { 'first': a, 'second': b }
    special_bar = bar.copy()
    special_bar.update(extra) # [1]
    special_function(**special_bar)
    normal_function(**bar)

[1] Да, я понимаю, что мог бы просто заменить эти две строки на extra.update(bar), но давайте предположим, что я хочу сохранить extra, как в дальнейшем в функции.

Я понимаю, что мог бы реализовать это сам таким образом:

def updated(old_dict, extra={}):
    new_dict = old_dict.copy()
    new_dict.update(extra)
    return new_dict

Или следующее крайне нечитаемое утверждение на месте:

    special_function(**(dict(bar.items()+extra.items())))

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

Ответы [ 3 ]

17 голосов
/ 28 февраля 2012

Вы можете просто использовать встроенный dict():

updated_dict = dict(old_dict, **extra_dict)
6 голосов
/ 28 февраля 2012

Если вам нужны не строковые ключи, вы можете использовать такую ​​функцию: (она не такая уродливая, как ваше выражение «на месте» + она работает для любого количества словарей)

from itertools import chain # ← credits go to Niklas B.

def updated(*dicts):
    return dict(chain(*map(dict.items, dicts)))

updated({42: 'the answer'}, {1337: 'elite'}) # {42: 'the answer', 1337: 'elite'}

В противном случае предложение Свена просто отлично.

Редактировать: Если вы используете Python 2.7 или более позднюю версию, вы также можете использовать словарное понимание, как предложил Свен в комментариях:

def updated(*dicts):
    return {k: v for d in dicts for k, v in d.items()}
4 голосов
/ 28 февраля 2012

Я действительно не вижу, что не так в использовании двух строк, как вы:

new_bar = bar.copy()
new_bar.update(extra)

Это чисто и читабельно.

>>> d = {1:2, 3:4}
>>> e = {3:9, 5:25}
>>> f = d.copy()
>>> f.update(e)
>>> d
{1: 2, 3: 4}
>>> f
{1: 2, 3: 9, 5: 25}
>>> e
{3: 9, 5: 25}

В трех словах: Zen of Python .

Чтобы быть более ясным: Я хочу сказать, что я бы не стал заменять эти две строки функцией updated(), которая не являетсяисходя из стандартной библиотеки.

Если бы я наткнулся на строку кода, такую ​​как:

new_bar = updated(bar, extra)

Я бы имел , чтобы отследить эту функцию и посмотреть, что она делает.Я не мог поверить, что в этом нет ничего странного.

ОП также сравнивал это с sorted(), но у sorted() есть причина существования, он действует на все, что можно повторять, и делает это спотрясающий тимсорт.Вместо этого должно быть поведение гипотетического updated()?Должно ли это быть dict метод класса?ИМХО, на самом деле, не совсем понятно.

Сказано, что можно выбрать две строки ОП, или решение Свена, или интеллектуальное понимание / генераторное выражение, я думаю, что это действительно просто вопрос вкуса.

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