Я пытаюсь «разрушить» словарь и связать значения с именами переменных после их ключей. Что-то вроде
params = {'a':1,'b':2}
a,b = params.values()
Но поскольку словари не упорядочены, нет гарантии, что params.values()
значения будут возвращены в порядке (a, b)
. Есть хороший способ сделать это?
python
sorting
dictionary
шляпа
источник
источник
let {a, b} = params
. Он улучшает читаемость и полностью соответствует тому дзен, о котором вы хотите поговорить.let {a: waffles} = params
. На это уходит несколько секунд, даже если вы к этому привыкли.Ответы:
Если вы опасаетесь проблем, связанных с использованием словаря местных жителей, и предпочитаете следовать своей исходной стратегии, Ordered Dictionaries из коллекций python 2.7 и 3.1. OrderedDicts позволяет восстанавливать элементы словаря в том порядке, в котором они были впервые вставлены
источник
from operator import itemgetter params = {'a': 1, 'b': 2} a, b = itemgetter('a', 'b')(params)
Вместо сложных лямбда-функций или понимания словаря можно также использовать встроенную библиотеку.
источник
attrgetter
тот же стандартный библиотечный модуль, который работает с атрибутами объекта (obj.a
). Это серьезное отличие от JavaScript, гдеobj.a === obj["a"]
.KeyError
будетa, b = [d[k] for k in ('a','b')]
вариант более естественен / читабелен (форма более распространена). Это все еще интересный ответ, но это не самое простое решение.get_id = itemgetter(KEYS)
использовать что-то вроде того, что позжеserial, code, ts = get_id(document)
. По общему признанию, вы должны хорошо разбираться в функциях высшего порядка, но Python, как правило, очень комфортно с ними. Например, см. Документацию для декораторов вроде@contextmanager
.Один из способов сделать это с меньшим количеством повторений, чем предлагает Йохен, - использовать вспомогательную функцию. Это дает возможность перечислять имена переменных в любом порядке и разрушать только подмножество того, что находится в dict:
pluck = lambda dict, *args: (dict[arg] for arg in args) things = {'blah': 'bleh', 'foo': 'bar'} foo, blah = pluck(things, 'foo', 'blah')
Кроме того, вместо OrderedDict joaquin вы можете отсортировать ключи и получить значения. Единственная загвоздка в том, что вам нужно указать имена переменных в алфавитном порядке и разрушить все в dict:
sorted_vals = lambda dict: (t[1] for t in sorted(dict.items())) things = {'foo': 'bar', 'blah': 'bleh'} blah, foo = sorted_vals(things)
источник
lambda
переменной a, вы также можете использовать обычный синтаксис функции сdef
.itemgetter
изoperator
стандартной библиотеки. :)Python может только «деструктурировать» последовательности, но не словари. Итак, чтобы написать то, что вы хотите, вам нужно будет сопоставить необходимые записи с правильной последовательностью. Что касается меня, самое близкое совпадение, которое я смог найти, - это (не очень сексуально):
a,b = [d[k] for k in ('a','b')]
Это также работает с генераторами:
a,b = (d[k] for k in ('a','b'))
Вот полный пример:
>>> d = dict(a=1,b=2,c=3) >>> d {'a': 1, 'c': 3, 'b': 2} >>> a, b = [d[k] for k in ('a','b')] >>> a 1 >>> b 2 >>> a, b = (d[k] for k in ('a','b')) >>> a 1 >>> b 2
источник
Может быть, вы действительно хотите сделать что-то подобное?
def some_func(a, b): print a,b params = {'a':1,'b':2} some_func(**params) # equiv to some_func(a=1, b=2)
источник
Вот еще один способ сделать это аналогично тому, как деструктурирующее присваивание работает в JS:
params = {'b': 2, 'a': 1} a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)
Что мы сделали, так это распаковали словарь параметров в ключевые значения (используя **) (как в ответе Йохена ), затем мы взяли эти значения в лямбда-сигнатуре и назначили их в соответствии с именем ключа - и вот бонус - мы также получите словарь всего, чего нет в сигнатуре лямбда, поэтому, если у вас есть:
params = {'b': 2, 'a': 1, 'c': 3} a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)
После применения лямбда остальная переменная теперь будет содержать: {'c': 3}
Полезно для исключения ненужных ключей из словаря.
Надеюсь это поможет.
источник
попробуй это
d = {'a':'Apple', 'b':'Banana','c':'Carrot'} a,b,c = [d[k] for k in ('a', 'b','c')]
результат:
a == 'Apple' b == 'Banana' c == 'Carrot'
источник
Предупреждение 1: как указано в документации, это не гарантируется для всех реализаций Python:
Предупреждение 2: эта функция делает код короче, но, вероятно, противоречит философии Python о максимальной ясности. Более того, он не решает проблемы, указанные Джоном Кристофером Джонсом в комментариях, хотя вы можете создать аналогичную функцию, которая работает с атрибутами вместо ключей. Это просто демонстрация того, что вы можете это сделать, если действительно захотите!
def destructure(dict_): if not isinstance(dict_, dict): raise TypeError(f"{dict_} is not a dict") # the parent frame will contain the information about # the current line parent_frame = inspect.currentframe().f_back # so we extract that line (by default the code context # only contains the current line) (line,) = inspect.getframeinfo(parent_frame).code_context # "hello, key = destructure(my_dict)" # -> ("hello, key ", "=", " destructure(my_dict)") lvalues, _equals, _rvalue = line.strip().partition("=") # -> ["hello", "key"] keys = [s.strip() for s in lvalues.split(",") if s.strip()] if missing := [key for key in keys if key not in dict_]: raise KeyError(*missing) for key in keys: yield dict_[key]
In [5]: my_dict = {"hello": "world", "123": "456", "key": "value"} In [6]: hello, key = destructure(my_dict) In [7]: hello Out[7]: 'world' In [8]: key Out[8]: 'value'
Это решение позволяет вам выбирать некоторые ключи, а не все, как в JavaScript. Это также безопасно для пользовательских словарей
источник
Что ж, если вы хотите, чтобы это было в классе, вы всегда можете сделать это:
class AttributeDict(dict): def __init__(self, *args, **kwargs): super(AttributeDict, self).__init__(*args, **kwargs) self.__dict__.update(self) d = AttributeDict(a=1, b=2)
источник
Основываясь на ответе @ShawnFumo, я придумал следующее:
def destruct(dict): return (t[1] for t in sorted(dict.items())) d = {'b': 'Banana', 'c': 'Carrot', 'a': 'Apple' } a, b, c = destruct(d)
(Обратите внимание на порядок элементов в dict)
источник
Поскольку словари гарантированно сохранят свой порядок вставки в Python> = 3.7 , это означает, что сейчас это совершенно безопасно и идиоматично:
params = {'a': 1, 'b': 2} a, b = params.values() print(a) print(b)
источник
b, a = params.values()
, поскольку он использует порядок, а не имена.itemgetter
- самый питонический способ сделать это. Это не будет работать на Python 3.6 или ниже, и, поскольку он зависит от порядка, поначалу это может сбивать с толку.Не знаю, хороший ли это стиль, но
locals().update(params)
сделает свое дело. Затем у вас есть
a
,b
и все , что было в вашемparams
dict, доступно как соответствующие локальные переменные.источник