복붙노트

[PYTHON] 전달 된 사전을 파이썬의 함수 이름 공간에 "압축을 풀"합니까?

PYTHON

전달 된 사전을 파이썬의 함수 이름 공간에 "압축을 풀"합니까?

필자가 수행하는 작업에서 편의를 위해 부분 집합으로 그룹화해야하는 매개 변수가 종종 있습니다.

d1 = {'x':1,'y':2}
d2 = {'a':3,'b':4}

여러 사전을 전달하여이 작업을 수행합니다. 대부분 나는 전달 된 사전을 직접 사용합니다. 즉 :

def f(d1,d2):
    for k in d1:
        blah( d1[k] )

일부 함수에서는 변수에 직접 액세스해야하므로 일이 번거로워집니다. 로컬 이름 공간에 이러한 변수가 실제로 필요합니다. 나는 다음과 같이 할 수 있기를 바란다 :

def f(d1,d2)
    locals().update(d1)
    blah(x)
    blah(y)    

그러나 locals ()가 반환하는 사전에 대한 업데이트는 실제로 네임 스페이스를 업데이트하는 것이 보장되지 않습니다.

확실한 수동 방법은 다음과 같습니다.

def f(d1,d2):
    x,y,a,b = d1['x'],d1['y'],d2['a'],d2['b']
    blah(x)
    return {'x':x,'y':y}, {'a':a,'b':b}

결과적으로 함수 당 세 번 반복됩니다. 장식자를 사용하여 자동화 할 수 있습니다.

def unpack_and_repack(f):
    def f_new(d1, d2):
        x,y,a,b = f(d1['x'],d1['y'],d2['a'],d3['b'])
        return {'x':x,'y':y}, {'a':a,'b':b}
    return f_new
@unpack
def f(x,y,a,b):
    blah(x)
    blah(y)
    return x,y,a,b

결과적으로 데코레이터에 3 번, 함수 당 2 번이 반복되므로 많은 기능을 가지고 있으면 더 좋습니다.

더 좋은 방법이 있습니까? 어쩌면 뭔가를 사용하여 평가? 감사!

해결법

  1. ==============================

    1.함수에 인수로 항상 사전을 전달할 수 있습니다. 예를 들어,

    함수에 인수로 항상 사전을 전달할 수 있습니다. 예를 들어,

    dict = {'a':1, 'b':2}
    def myFunc(a=0, b=0, c=0):
        print(a,b,c)
    myFunc(**dict)
    
  2. ==============================

    2.d.variable 문법이 d [ 'variable']보다 낫다면 다음과 같이 거의 사소한 "묶음"객체로 사전을 감쌀 수 있습니다 :

    d.variable 문법이 d [ 'variable']보다 낫다면 다음과 같이 거의 사소한 "묶음"객체로 사전을 감쌀 수 있습니다 :

    class Bunch:
        def __init__(self, **kw):
            self.__dict__.update(kw)
    

    사전 내용을 로컬 네임 스페이스에 정확하게 가져올 수는 없지만 개체에 짧은 이름을 사용하면 닫을 수 있습니다.

  3. ==============================

    3.사전에있는 모든 키가 식별자가 될 수 있다고 가정하면, 다음과 같이하면됩니다.

    사전에있는 모든 키가 식별자가 될 수 있다고 가정하면, 다음과 같이하면됩니다.

    adict = { 'x' : 'I am x', 'y' : ' I am y' }
    for key in  adict.keys():
      exec(key + " = adict['" + key + "']")
    blah(x)
    blah(y)
    
  4. ==============================

    4.이것은 locals ()로 사용하는 것입니다. update (d1) workaround :

    이것은 locals ()로 사용하는 것입니다. update (d1) workaround :

    def f(d1,d2)
        exec ','.join(d1) + ', = d1.values()'
        blah(x)
        blah(y)
    
  5. ==============================

    5.이는 장식 자 아이디어와 비슷하지만 좀 더 일반적입니다. 임의의 수의 dict을 foo에 전달할 수 있으며 장식자는 dicts의 키 또는 해당 키의 순서에 대해 알 필요가 없습니다. 기본 foo 함수를 호출 할 때 인수.

    이는 장식 자 아이디어와 비슷하지만 좀 더 일반적입니다. 임의의 수의 dict을 foo에 전달할 수 있으며 장식자는 dicts의 키 또는 해당 키의 순서에 대해 알 필요가 없습니다. 기본 foo 함수를 호출 할 때 인수.

    #!/usr/bin/env python
    d1 = {'x':1,'y':2}
    d2 = {'a':3,'b':4}
    
    def unpack_dicts(f):
        def f_new(*dicts):
            new_dict={}
            for d in dicts:
                new_dict.update(d)
            return f(**new_dict)
        return f_new
    
    @unpack_dicts
    def foo(x,y,a,b):
        print x,y,a,b
    
    foo(d1,d2)
    # 1 2 3 4
    
  6. ==============================

    6.나는 파이썬에서 dict을 풀 때 더 이상 편리함을 얻을 수 없다고 생각한다. 그래서, 여기에 의무적 인 "만약 그것이 아프다면, 그렇게하지 마십시오"라는 대답이옵니다.

    나는 파이썬에서 dict을 풀 때 더 이상 편리함을 얻을 수 없다고 생각한다. 그래서, 여기에 의무적 인 "만약 그것이 아프다면, 그렇게하지 마십시오"라는 대답이옵니다.

    항목 액세스를 매핑하는 것은 Python의 속성 액세스보다 더 복잡하므로 dict 대신 사용자 정의 클래스의 인스턴스를 전달해야합니다.

  7. ==============================

    7.한 라이너에서 언 패킹 방법은 다음과 같습니다.

    한 라이너에서 언 패킹 방법은 다음과 같습니다.

    (x ','b ':'y ','c ':'z ') x, y = (λa, b,

    람다 args a와 b는 x와 y의 순서로 언팩하고 싶은 키입니다. ** _ 사전에있는 다른 모든 키를 무시합니다 (예 : c).

  8. ==============================

    8.공통된 지혜는 "생산 코드에서 inspect 모듈을 사용하지 마십시오"라고 생각합니다. 따라서 프로덕션 코드에서 다음을 수행하는 것은 좋지 않은 생각입니다. 그러나 프레임을 지원하는 파이썬 (CPython과 같은)에서 작업하는 중이면 다음과 같이 작동해야합니다.

    공통된 지혜는 "생산 코드에서 inspect 모듈을 사용하지 마십시오"라고 생각합니다. 따라서 프로덕션 코드에서 다음을 수행하는 것은 좋지 않은 생각입니다. 그러나 프레임을 지원하는 파이썬 (CPython과 같은)에서 작업하는 중이면 다음과 같이 작동해야합니다.

    >>> def framelocals():
    ...    return inspect.currentframe(1).f_locals
    ... 
    >>> def foo(ns):
    ...    framelocals().update(ns)
    ...    print locals()
    ... 
    >>> foo({'bar': 17})
    {'ns': {'bar': 17}, 'bar': 17}
    

    함수 몸체 안에서 호출 될 때 함수의 이름 공간이어야하는 호출자의 프레임에서 실제 dict을 꺼내기 만하면됩니다. locals ()가 어쨌든이 작업을 수행하지 않을 때 CPython을 사용할 때 상황이 있는지 여부는 알 수 없습니다. 문서의 경고는 "locals ()에 의해 반환 된 dict 수정의 효과는 파이썬 구현에 따라 달라집니다"라고 말할 수 있습니다. 따라서, CPython에서 그 dict을 수정하는 동안, 다른 구현에서는 그렇지 않을 수도 있습니다.

    업데이트 :이 방법은 실제로 작동하지 않습니다.

    >>> def flup(ns):
    ...    framelocals().update(ns)
    ...    print locals()
    ...    print bar
    ... 
    >>> flup({'bar': 17})
    {'ns': {'bar': 17}, 'bar': 17}
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 4, in flup
    NameError: global name 'bar' is not defined
    

    ddaa가 제안했듯이, 지역 변수를 기록하는 함수 컴파일에 더 깊은 마법이 있습니다. 따라서 dict를 업데이트 할 수는 있지만 일반 로컬 네임 스페이스 조회로 업데이트를 볼 수는 없습니다.

  9. ==============================

    9.편리하게 사용할 수있는 인수를 번들 링하거나 풀어 내기위한 var_arguments라는 Python 패키지를 작성했습니다. github에서 사용할 수 있습니다.

    편리하게 사용할 수있는 인수를 번들 링하거나 풀어 내기위한 var_arguments라는 Python 패키지를 작성했습니다. github에서 사용할 수 있습니다.

    글쓰기 대신 말하기 :

    def f(d1,d2):
        x,y,a,b = d1['x'],d1['y'],d2['a'],d2['b']
        y=x+a
        return {'x':x,'y':y}, {'a':a,'b':b}
    

    다음과 같이 작성할 수 있습니다.

    from var_arguments import recon_dict, use_dargs
    
    def f(d1,d2):
      r=f2(dargs=[d1,d2])
      return recon_dict(d1,r), recon_dict(d2,r)
    
    @use_dargs
    def f2(x,y,a,b):
      y=x+a
      return locals()
    

    당신이 생각하는 것과 일치하는 솔루션을 썼습니다. 사전은 그룹으로 나옵니다. 우리는 사전에 키의 이름을 언급하거나 수동으로 액세스하는 횟수를 최소화합니다. 특히 x, y, a 및 b는이 방법으로 언급하면됩니다.

    기본적으로 @use_dargs는 f2를 수정하여 선택적인 dargs 키워드 인수를 허용하며, 존재하는 경우 사전 목록을 제공해야합니다 (dargs = [d1, d2]). 키 / 값 이러한 사전의 쌍은 그렇지 않으면 함수에 대한 호출에 제공되는 키워드 인수에 추가되며, 키워드 인수는 가장 높은 우선 순위를 가지며 d2는 두 번째로 높은 값을 갖습니다. d1은 우선 순위가 가장 낮습니다. 따라서 f2를 다양한 방법으로 호출하여 동일한 결과를 얻을 수 있습니다.

    f2(1,2,3,4)
    f2(1,a=3,dargs=[dict(y=2,b=4)])
    f2(dargs=[dict(x=1,y=2),dict(a=3,b=4)])
    

    recon_dict는 이전 값이 들어있는 사전이 하나있는 경우입니다. 관심있는 모든 키와 키를 보유하고있는 다른 사전 모든 키에 대한 새로운 값 (원하지 않는 다른 값). 예 :

    old_d=dict(a=8,b=9) # I want these keys, but they're old values
    xyab=dict(x=1,y=2,a=3,b=4) # These are the new values, but I don't want all of them
    new_d=recon_dict(old_d,xyab)
    assert new_d==dict(a=3,b=4)
    

    다음은 var_arguments가 처리하는 함수 본문 내에서 변수 이름을 여러 번 언급하는 중복성을 제거하는 몇 가지 추가 트릭입니다. 먼저, 다음을 변경할 수 있습니다.

    {'x':x,'y':y}
    

    으로:

    ddict('x,y',locals())
    

    마찬가지로 다음을 변경할 수 있습니다.

    f(x=x,y=y)
    

    으로:

    dcall(f,'x,y',locals())
    

    보다 일반적으로 우리가 키 x와 y를 가진 사전 xy를 가지고 있고 지역 변수에 a와 b가 포함되어 있다면 다음과 같이 바꿀 수 있습니다 :

    f(x=xy['x'],y=xy['y'],a=a,b=b)
    

    으로:

    ldcall(f,'x,y,a,b',[locals(),xy])
    
  10. ==============================

    10.마법을 사용할 수 있습니다 :

    마법을 사용할 수 있습니다 :

    from sorcery import unpack_dict
    
    x, y = unpack_dict(d1)
    
  11. from https://stackoverflow.com/questions/1897623/unpacking-a-passed-dictionary-into-the-functions-name-space-in-python by cc-by-sa and MIT license