source

파괴 바인딩된 사전 내용

bestscript 2023. 7. 19. 22:40

파괴 바인딩된 사전 내용

사전을 '구조화'하고 키 뒤에 있는 변수 이름과 값을 연결하려고 합니다.비슷한 것

params = {'a':1,'b':2}
a,b = params.values()

하지만 사전이 주문되지 않았기 때문에, 그것은 보장되지 않습니다.params.values()다음 순서로 값을 반환합니다.(a, b)이것을 하는 좋은 방법이 있습니까?

from operator import itemgetter

params = {'a': 1, 'b': 2}

a, b = itemgetter('a', 'b')(params)

정교한 람다 함수나 사전 이해 대신 내장 라이브러리를 사용할 수도 있습니다.

왜 아무도 가장 간단한 접근법을 게시하지 않았습니까?

params = {'a':1,'b':2}

a, b = params['a'], params['b']

Jochen의 제안보다 적은 반복으로 이를 수행하는 한 가지 방법은 도우미 기능을 사용하는 것입니다.이를 통해 변수 이름을 임의의 순서로 나열하고 딕트의 하위 집합만 재구성할 수 있습니다.

pluck = lambda dict, *args: (dict[arg] for arg in args)

things = {'blah': 'bleh', 'foo': 'bar'}
foo, blah = pluck(things, 'foo', 'blah')

또한 호아킨의 OrderedDict 대신 키를 정렬하고 값을 얻을 수 있습니다.변수 이름을 알파벳 순으로 지정하고 딕트의 모든 내용을 재구성해야 합니다.

sorted_vals = lambda dict: (t[1] for t in sorted(dict.items()))

things = {'foo': 'bar', 'blah': 'bleh'}
blah, foo = sorted_vals(things)

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

JS에서 파괴 할당이 작동하는 방식과 유사하게 이를 수행하는 다른 방법은 다음과 같습니다.

params = {'b': 2, 'a': 1}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)

우리가 한 것은 params 사전을 키 값으로 압축 해제하는 것이었습니다 (*를 사용하여) (Jochen의 답변처럼). 그런 다음 람다 서명에 있는 값을 키 이름에 따라 할당했습니다. 그리고 여기 보너스가 있습니다. 우리는 람다 서명에 없는 것에 대한 사전도 제공합니다. 그래서 만약 당신이 다음을 가지고 있다면:

params = {'b': 2, 'a': 1, 'c': 3}
a, b, rest = (lambda a, b, **rest: (a, b, rest))(**params)

람다가 적용되면 나머지 변수에 다음이 포함됩니다. {'c': 3}

사전에서 불필요한 키를 생략하는 데 유용합니다.

이게 도움이 되길 바랍니다.

정말 이런 일을 하고 싶으신가요?

def some_func(a, b):
  print a,b

params = {'a':1,'b':2}

some_func(**params) # equiv to some_func(a=1, b=2)

로컬 사전 사용과 관련된 문제가 두려워 원래 전략인 python 2.7 및 3.1 컬렉션의 Ordered Dictionary를 따르는 것을 선호하는 경우.OrderedDicts를 사용하면 사전 항목을 처음 삽입한 순서대로 복구할 수 있습니다.

(Ab) 가져오기 시스템 사용

from ... import문을 사용하여 개체의 특성 이름을 분리하고 바인딩할 수 있습니다.물론, 그것은 단지 안에 있는 물체들에 대해서만 작동합니다.sys.modules사전, 그래서 사람들은 다음과 같은 해킹을 사용할 수 있습니다.

import sys, types

mydict = {'a':1,'b':2}

sys.modules["mydict"] = types.SimpleNamespace(**mydict)

from mydict import a, b

좀 더 심각한 해킹은 컨텍스트 관리자를 작성하여 모듈을 로드하고 언로드하는 것입니다.

with obj_as_module(mydict, "mydict_module"):
    from mydict_module import a, b

다음을 가리킴으로써__getattr__모듈의 방식을 직접적으로__getitem__딕트의 방법, 컨텍스트 관리자는 또한 사용을 피할 수 있습니다.SimpleNamespace(**mydict).

구현 및 아이디어의 일부 확장은 이 답변을 참조하십시오.

또한 임시로 전체를 대체할 수도 있습니다.sys.modules관심의 받아쓰기로 받아쓰기, 그리고 하기.import a, b없이.from.

경고 1: 문서에 명시된 대로 모든 Python 구현에서 이 작업이 작동하는 것은 아닙니다.

Cython 구현 세부 정보:이 함수는 인터프리터의 Python 스택 프레임 지원에 의존하며, 이는 Python의 모든 구현에 존재하는 것으로 보장되지 않습니다.Python 스택 프레임을 지원하지 않는 구현에서 실행되는 경우 이 함수는 없음을 반환합니다.

경고 2: 이 함수는 코드를 더 짧게 만들지만, 가능한 한 명시적이라는 파이썬 철학과 모순될 수 있습니다.또한 키 대신 속성으로 작동하는 유사한 기능을 만들 수 있지만 John Christopher Jones가 코멘트에서 지적한 문제를 다루지 않습니다.이것은 여러분이 정말 원한다면 그렇게 할 수 있다는 것을 보여주는 것입니다!

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에서처럼 일부 키를 선택할 수 있습니다.또한 사용자가 제공하는 사전에도 안전합니다.

Python 3.10을 사용하면 다음을 수행할 수 있습니다.

d = {"a": 1, "b": 2}

match d:
    case {"a": a, "b": b}:
        print(f"A is {a} and b is {b}")

두 단계의 들여쓰기가 추가되고 키 이름을 반복해야 합니다.

사전의 예상치 못한 순서를 따르지 않으므로 다른 답을 찾으십시오. 곧 올바른 버전으로 업데이트할 것입니다.

이것을 먹어보세요.

data = {'a':'Apple', 'b':'Banana','c':'Carrot'}
keys = data.keys()
a,b,c = [data[k] for k in keys]

결과:

a == 'Apple'
b == 'Banana'
c == 'Carrot'

클래스에서 이러한 기능을 사용하려면 항상 다음 작업을 수행할 수 있습니다.

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로 작성된 항목의 순서에 주의)

오래된 주제지만, 저는 이것이 유용한 방법이라는 것을 알았습니다.

data = {'a':'Apple', 'b':'Banana','c':'Carrot'}
for key in data.keys():
    locals()[key] = data[key]

이 메서드는 사전의 모든 키를 루프하여 해당 이름으로 변수를 설정한 다음 관련 키의 값을 이 새 변수에 할당합니다.

테스트:

print(a)
print(b)
print(c)

산출량

Apple
Banana
Carrot

쉽고 간단한 파괴 방법dict파이썬:

params = {"a": 1, "b": 2}
a, b = [params[key] for key in ("a", "b")]
print(a, b)
# Output:
# 1 2

아니요, 현재 Python에서는 이를 수행하는 좋은 방법이 없습니다.

제 책에서 "좋음"으로 인정받기 위해서는 과제에서 사전 키를 반복하는 것을 피해야 합니다.

그림:

from operator import itemgetter

params = {'a_very_long_name': 1, 'b': 2}

# Not nice solution, we still have to spell out 'a_very_long_name' twice
a_very_long_name, b = itemgetter('a_very_long_name', 'b')(params)

Instead, the most readable way to write this in Python is:

params = {'a_very_long_name': 1, 'b': 2}

a_very_long_name = params['a_very_long_name']
b = params['b']

In Javascript, there is a specific syntax for Object destructuring:

const params = {a_very_long_name: 1, b: 2};

const {a_very_long_name, b} = params;

If you have a Javascript background, you may be tempted to look for the same in Python. But Python is not Javascript, and it doesn't have this feature. This doesn't make Python inferior, it's just a different design decision, and the best way to deal with it is to accept it rather than trying to replicate the "Javascript-way" of writing code.

I don't know whether it's good style, but

locals().update(params)

할 수 있을 겁니다그렇다면 당신은a,b그리고 당신의 안에 있던 것이 무엇이든.paramsdict를 해당 로컬 변수로 사용할 수 있습니다.

Since dictionaries are guaranteed to keep their insertion order in Python >= 3.7, that means that it's complete safe and idiomatic to just do this nowadays:

params = {'a': 1, 'b': 2}
a, b = params.values()
print(a)
print(b)

Output:

1
2

ReferenceURL : https://stackoverflow.com/questions/2955412/destructuring-bind-dictionary-contents