sourcetip

python dict.update()가 개체를 반환하지 않는 이유는 무엇입니까?

fileupload 2023. 6. 7. 23:06
반응형

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

하지만 코드는 다소 번거롭게 느껴졌습니다.저는 다음과 같은 글을 쓸 수 있었으면 좋았을 것입니다.

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

왜안그요래?요'래▁the▁whyt그▁doesn?updatereturnJQuery에서 작동하는 방식과 같이 체인을 허용하는 원본 사전?왜 파이썬에서는 허용되지 않습니까?


Python에서 의 사전을 단일 식으로 병합하는 방법을 참조하십시오.회피책으로

Python은 대부분 실용적으로 구현된 명령 쿼리 분리: 돌연변이가 반환됩니다.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등).

Python의 API는 전통적으로 절차와 기능을 구분합니다.함수는 매개 변수(대상 개체 포함)에서 새 값을 계산합니다. 프로시저는 개체를 수정하고 아무것도 반환하지 않습니다(예: 없음을 반환함).그래서 절차에는 부작용이 있지만, 기능에는 영향이 없습니다.업데이트는 절차이므로 값을 반환하지 않습니다.

그렇게 하는 이유는 그렇지 않으면 바람직하지 않은 부작용이 생길 수 있기 때문입니다.고려하다

bar = foo.reverse()

역방향(목록 삽입을 반대로 함)도 목록을 반환하는 경우, 사용자는 역방향이 막대에 할당된 새 목록을 반환한다고 생각할 수 있으며, foo도 수정된다는 사실을 눈치채지 못할 수 있습니다.역귀환을 없음으로 설정하면 막대가 역귀환의 결과가 아님을 즉시 인식하고 역귀환의 효과가 무엇인지 더 자세히 볼 수 있습니다.

이는 다음과 같이 쉽습니다.

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

또는 사전을 수정하지 않는 것이 중요한 경우:

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

상위 답변에 댓글을 달기에 충분한 평판이 없습니다.

@beardc 이것은 Cython 일이 아닌 것 같습니다.PyPy는 "TypeError: 키워드는 문자열이어야 함"을 제공합니다.

솔루션과 함께 제공하는 솔루션**kwargs병합할 사전에는 문자열 유형의 키만 있기 때문에 작동합니다.

예.

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

>>> dict({1:2}, **{'3':4})
{1: 2, '3': 4}
>>> 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_merge(a,b)는 a를 수정합니다.

물론 모든 작업을 인라인으로 수행할 수도 있습니다.

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

받아들일 수 없는 것이 아니라, 오히려.dicts그런 식으로 구현되지 않았습니다.

장고의 ORM을 보면 체인을 광범위하게 활용하고 있습니다.낙담하지 않고, 당신은 심지어 상속받을 수 있습니다.dict오버라이드만 가능합니다.update업데이트를 수행return self당신이 정말 원한다면요.

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

파티에 늦게 오는 사람들을 위해, 나는 어느 정도의 타이밍을 맞춰놓았습니다 (Py 3.7)..update()기반 방법은 입력이 보존될 때는 약간(~5%) 빨라지고, 인플레이스 업데이트만 할 때는 눈에 띄게(~30%) 빨라집니다.

여느 때처럼 모든 벤치마크를 고려해야 합니다.

def join2(dict1, dict2, inplace=False):
    result = dict1 if inplace else dict1.copy()
    result.update(dict2)
    return result


def join(*items):
    iter_items = iter(items)
    result = next(iter_items).copy()
    for item in iter_items:
        result.update(item)
    return result


def update_or(dict1, dict2):
    return dict1.update(dict2) or dict1


d1 = {i: str(i) for i in range(1000000)}
d2 = {str(i): i for i in range(1000000)}

%timeit join2(d1, d2)
# 258 ms ± 1.47 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit join(d1, d2)
# 262 ms ± 2.97 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit dict(d1, **d2)
# 267 ms ± 2.74 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit {**d1, **d2}
# 267 ms ± 1.84 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

인플레이스 작업의 타이밍은 좀 더 까다롭기 때문에 추가 복사 작업을 통해 수정해야 합니다(첫 번째 타이밍은 참조용일 뿐입니다.

%timeit dd = d1.copy()
# 44.9 ms ± 495 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit dd = d1.copy(); join2(dd, d2)
# 296 ms ± 2.05 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit dd = d1.copy(); join2(dd, d2, True)
# 234 ms ± 1.02 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit dd = d1.copy(); update_or(dd, d2)
# 235 ms ± 1.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
import itertools
dict_merge = lambda *args: dict(itertools.chain(*[d.iteritems() for d in args]))

가능한 한 당신의 제안된 해결책에 가깝습니다.

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

방금 파이썬 3.4에서 직접 시도했습니다(그래서 그 공상을 사용할 수 없었습니다).{**dict_1, **dict_2}구문)을 선택합니다.

저는 임의의 양의 사전을 제공할 뿐만 아니라 사전에 문자열이 아닌 키를 가질 수 있기를 원했습니다.

또한, 나는 새로운 사전을 만들고 싶어서 사용하지 않기로 결정했습니다.collections.ChainMap(kinda 내가 사용하고 싶지 않은 이유.dict.update초판에

제가 쓴 글은 다음과 같습니다.

def merge_dicts(*dicts):
    all_keys  = set(k for d in dicts for k in d.keys())
    chain_map = ChainMap(*reversed(dicts))
    return {k: chain_map[k] for k in all_keys}

merge_maps({'1': 1}, {'2': 2, '3': 3}, {'1': 4, '3': 5})
# {'1': 4, '3': 5, '2': 2}

항목 목록을 연결하여 병합:

d1 = {1: "one"}
d2 = {2: "two"}
dict(list(d1.items()) + list(d2.items()))
# {1: 'one', 2: 'two'}

언급URL : https://stackoverflow.com/questions/1452995/why-doesnt-a-python-dict-update-return-the-object

반응형