[python] 파이썬 dict.update ()가 객체를 반환하지 않는 이유는 무엇입니까?

나는 노력하고있다 :

award_dict = {
    "url" : "http://facebook.com",
    "imageurl" : "http://farm4.static.flickr.com/3431/3939267074_feb9eb19b1_o.png",
    "count" : 1,
}

def award(name, count, points, desc_string, my_size, parent) :
    if my_size > count :
        a = {
            "name" : name,
            "description" : desc_string % count,
            "points" : points,
            "parent_award" : parent,
        }
        a.update(award_dict)
        return self.add_award(a, siteAlias, alias).award

그러나 기능이 정말 번거 롭다면 오히려했을 것입니다.

        return self.add_award({
            "name" : name,
            "description" : desc_string % count,
            "points" : points,
            "parent_award" : parent,
        }.update(award_dict), siteAlias, alias).award

체인을 연결할 수 있도록 업데이트가 객체를 반환하지 않는 이유는 무엇입니까?

JQuery는이를 수행하여 체인을 수행합니다. 파이썬에서는 왜 허용되지 않습니까?



답변

파이썬은 주로 명령 쿼리 분리 의 실용적으로 색을 입힌 풍미를 구현합니다 : 뮤 테이터는 None(;-와 같은 실용적으로 예외가 발생 pop하여) 접근 자와 혼동 할 수 없으므로 반환합니다 ( 같은 맥락에서 할당은 표현이 아닙니다. -표현 분리 등이 있습니다).

즉 당신이 정말로 원하는 경우 병합 것들까지 많은 방법이 예는,이없는 것은 아닙니다 dict(a, **award_dict)많이 원하는 것으로 보인다 것과 같은 새로운 딕셔너리하게 .update왜 당신이 정말로 느끼는 경우가 중요하다는 것을 사용하지 – 반환 ?

편집 : btw, 특정 경우에 a따라 길을 따라 만들 필요가 없습니다 .

dict(name=name, description=desc % count, points=points, parent_award=parent,
     **award_dict)

정확히 같은 의미로 하나의 딕셔너리를 생성하여 a.update(award_dict)(충돌의 경우, 항목 사실을 포함하여 award_dict명시 적으로 제공하고 그 재정의, 즉, 다른 의미를 얻기 위해이 같은 충돌을 “승리”명시 적 항목을 가지고, 키워드 위치 앞에award_dict 유일한 위치 인수 로 전달 하고 형식 등의 구부러짐 등).**dict(award_dict, name=name


답변

파이썬의 API는 관례에 따라 프로 시저와 함수를 구분합니다. 함수는 매개 변수에서 새 값을 계산합니다 (대상 객체 포함). 프로 시저는 객체를 수정하고 아무것도 반환하지 않습니다 (즉, None을 반환합니다). 따라서 절차에는 부작용이 있지만 기능에는 없습니다. 업데이트는 절차이므로 값을 반환하지 않습니다.

그렇게하는 동기는 그렇지 않으면 바람직하지 않은 부작용이 생길 수 있다는 것입니다. 치다

bar = foo.reverse()

reverse (제자리에서 목록을 뒤집는)가 목록을 반환 할 경우 사용자는 reverse가 bar에 할당 된 새 목록을 반환한다고 생각할 수 있으며 foo도 수정된다는 사실을 절대 알 수 없습니다. 리버스 리턴 없음을 설정하면 바가 반전의 결과가 아니라는 것을 즉시 인식하고 리버스의 효과가 더 가깝게 보입니다.


답변

다음과 같이 쉽습니다.

(lambda d: d.update(dict2) or d)(d1)


답변

>>> dict_merge = lambda a,b: a.update(b) or a
>>> dict_merge({'a':1, 'b':3},{'c':5})
{'a': 1, 'c': 5, 'b': 3}

병합 된 dict를 반환 할뿐만 아니라 첫 번째 매개 변수를 그 자리에서 수정합니다. 따라서 dict_merge (a, b)는 a를 수정합니다.

또는 물론 인라인으로 모두 할 수 있습니다.

>>> (lambda a,b: a.update(b) or a)({'a':1, 'b':3},{'c':5})
{'a': 1, 'c': 5, 'b': 3}


답변

댓글에 대한 평판이 충분하지 않습니다.

@ beardc 이것은 CPython이 아닌 것 같습니다. PyPy에서 “TypeError : 키워드는 문자열이어야합니다”

**kwargs병합 할 사전에 string 유형의 키만 있기 때문에 솔루션 만 작동 합니다 .

>>> dict({1:2}, **{3:4})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: keyword arguments must be strings

vs

>>> dict({1:2}, **{'3':4})
{1: 2, '3': 4}


답변

허용되지 않는 것이 아니라 dicts그 방식으로 구현되지 않았습니다.

Django의 ORM을 보면 체인을 광범위하게 사용합니다. 권장하지 않으며 업데이트를 수행하기 위해 상속 dict하고 재정의 updatereturn self수도 있습니다.

class myDict(dict):
    def update(self, *args):
        dict.update(self, *args)
        return self


답변

내가 얻을 수있는 제안 된 솔루션에 가깝습니다.

from collections import ChainMap

return self.add_award(ChainMap(award_dict, {
    "name" : name,
    "description" : desc_string % count,
    "points" : points,
    "parent_award" : parent,
}), siteAlias, alias).award