日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python dict get 怎么实现的_关于python:dict.get()方法返回一个指针

發(fā)布時間:2024/1/8 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python dict get 怎么实现的_关于python:dict.get()方法返回一个指针 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

假設(shè)我有這個代碼:

my_dict = {}

default_value = {'surname': '', 'age': 0}

# get info about john, or a default dict

item = my_dict.get('john', default_value)

# edit the data

item[surname] = 'smith'

item[age] = 68

my_dict['john'] = item

如果我們現(xiàn)在檢查默認值,問題就變得很明顯了:

>>> default_value

{'age': 68, 'surname': 'smith'}

很明顯,my_dict.get()沒有返回默認值,而是返回一個指針(?)對它。

通過將代碼更改為:

item = my_dict.get('john', {'surname': '', 'age': 0})

但這似乎不是一個很好的方法。有什么想法,意見嗎?

item = my_dict.get('john', default_value.copy())

您總是在python中傳遞一個引用。

對于不可變的對象,如str、int、tuple等,這并不重要。因為您不能更改它們,所以只能將名稱指向不同的對象,但對于易變的對象,如list、set和dict,它確實如此。你需要習(xí)慣這一點并時刻牢記在心。

編輯:ZachBloom和JonathanSternberg都指出了避免每次查找時調(diào)用copy的方法。您應(yīng)該使用defaultdict方法,類似于jonathan的第一種方法,或者:

def my_dict_get(key):

try:

item = my_dict[key]

except KeyError:

item = default_value.copy()

如果dict很大,當(dāng)密鑰幾乎總是存在于my_dict中時,這將比if更快。您不必將它包裝在函數(shù)中,但您可能不希望每次訪問my_dict時都使用這四行。

看喬納森的回答,他用一個小的dict計時。在我測試的所有尺寸中,get方法表現(xiàn)不佳,但在大尺寸中,try方法表現(xiàn)更好。

這是Python的一個非常重要的原則——所有值都是通過引用傳遞的。這些引用的可變性是一個完全不同的問題(盡管它經(jīng)常以這種方式絆倒人們)。

我肯定我以前讀過,但當(dāng)你長時間不使用一種語言時,你往往會忘記一些事情。謝謝你說的清楚。

為什么你的答案與問題中提供的答案有任何不同?問題似乎更多的是找到一種優(yōu)雅的方法來返回新的dict實例,但只在需要時創(chuàng)建它。

問題是,他不必每次都輸入{'surname': '', 'age': 0},也不必每次都輸入get,而是通過擴展說明如何在python中傳遞參數(shù),而不必每次都創(chuàng)建參數(shù)。不過,我已經(jīng)指出了其他提到這個問題的答案,并添加了一個備選方案。

@請看我的速度計時答案。使用try/except會比他想要的慢得多。

我做了更多的計時,而且對于任何一個dict大小的get方法都不快,這讓我感到驚訝。但是,try方法比對大型dict的雙重查找要快,大約10000-1000000個條目的查找速度為10%。如果命中率很高,那么使用try是值得的。

-1:所有的值都在python中被賦值和傳遞。Python中的所有值都是引用(與Java中的非原語相同)。pass-by-reference"有一個非常具體的含義,即可以在調(diào)用范圍內(nèi)重新分配變量,而在python中則不是這樣。參見stackoverflow.com/questions/986006

是的,我在簡化。我將編輯為說"你總是傳遞一個引用",而不是"通過引用",以免混淆那些可能從字面上理解它的人。

@agf:請注意,在調(diào)用my_dict.get('john', default_value.copy())時,即使我的字典中有"john",default_value.copy()也會被執(zhí)行:即使沒有返回,也會創(chuàng)建一個默認值的副本。這解釋了使用get方法時的部分性能問題。

@是的,我知道。你讀過這篇文章的其余部分嗎?或者其他答案?這就是整條線的意義所在。即使在其他構(gòu)造中使用dict.get(),它仍然有使用關(guān)鍵字不需要的開銷。

@阿格夫:你說得對,我現(xiàn)在明白了,你和其他人確實提到過;對不起,我該閉嘴睡覺了……

@雷米哈哈,抱歉最后一句話的語氣,我貼出來的時候,實際上我正要去睡覺。

不要使用GET。你可以這樣做:

item = my_dict.get('john', default_value.copy())

但這要求即使字典條目存在,也要復(fù)制字典。相反,考慮檢查值是否存在。

item = my_dict['john'] if 'john' in my_dict else default_value.copy()

唯一的問題是它將對"john"執(zhí)行兩次查找,而不是一次。如果您愿意使用一個額外的行(并且沒有一個是您從字典中得到的可能值),您可以這樣做:

item = my_dict.get('john')

if item is None:

item = default_value.copy()

編輯:我想我會和timeit做一些速度比較。默認值和我的口述是全局的。如果鑰匙在那里,如果有失手的話,我會為兩個人都做。

使用例外:

def my_dict_get():

try:

item = my_dict['key']

except KeyError:

item = default_value.copy()

# key present: 0.4179

# key absent: 3.3799

使用get并檢查它是否為none。

def my_dict_get():

item = my_dict.get('key')

if item is None:

item = default_value.copy()

# key present: 0.57189

# key absent: 0.96691

使用特殊的if/else語法檢查其存在性

def my_dict_get():

item = my_dict['key'] if 'key' in my_dict else default_value.copy()

# key present: 0.39721

# key absent: 0.43474

天真地抄寫字典。

def my_dict_get():

item = my_dict.get('key', default_value.copy())

# key present: 0.52303 (this may be lower than it should be as the dictionary I used was one element)

# key absent: 0.66045

在大多數(shù)情況下,除了使用異常的情況外,其他情況都非常相似。由于某種原因,特殊的if/else語法的時間似乎最短(不知道為什么)。

這是一個很好的觀點,我會在我的答案中加上一個注釋。用'john' in my_dict代替my_dict.has_key('john'),用my_dict.get('john')代替my_dict.get('john', None),怎么樣?

我喜歡使用in,而不是has-key。我忘記了這一點。我不知道我的dict.get("john")默認返回空值(我認為這是一個indexerror)。

或者使用這個:從集合導(dǎo)入defaultdict mydict=defaultdict(default_value.copy),然后在執(zhí)行mydict[此處沒有的鍵]時,將調(diào)用傳遞給構(gòu)造函數(shù)的函數(shù)。

在python中,dict都是對象(因此它們總是作為引用傳遞)和可變對象(這意味著它們可以在不重新創(chuàng)建的情況下進行更改)。

每次使用詞典時,您都可以復(fù)制詞典:

my_dict.get('john', default_value.copy())

還可以使用defaultdict集合:

from collections import defaultdict

def factory():

return {'surname': '', 'age': 0}

my_dict = defaultdict(factory)

my_dict['john']

要認識到的主要事情是,Python中的所有內(nèi)容都是通過引用傳遞的。C樣式語言中的變量名通常是內(nèi)存中對象形狀區(qū)域的簡寫,將該變量賦值可復(fù)制另一個對象形狀區(qū)域…在Python中,變量只是字典(locals()中的鍵),而賦值操作只存儲新的引用。(從技術(shù)上講,一切都是一個指針,但這是一個實現(xiàn)細節(jié))。

這有許多含義,主要的含義是永遠不會有一個對象的隱式副本,因為您將它傳遞給了一個函數(shù),分配了它,等等。獲得副本的唯一方法是顯式地這樣做。python stdlib提供了一個copy模塊,該模塊包含一些內(nèi)容,包括copy()和deepcopy()函數(shù),當(dāng)您想要顯式地復(fù)制某個內(nèi)容時。此外,有些類型公開了自己的.copy()功能,但這不是標準,也不是一貫實現(xiàn)的。其他不可變的方法有時會提供一個.replace()方法,這會產(chǎn)生一個變異的拷貝。

在代碼的情況下,傳遞原始實例顯然不起作用,并且提前(可能不需要時)制作一個副本是浪費的。所以最簡單的解決方案可能是…

item = my_dict.get('john')

if item is None:

item = default_dict.copy()

在這種情況下,如果.get()支持傳入默認值構(gòu)造函數(shù)函數(shù),這將非常有用,但這可能是在為邊界情況設(shè)計一個基類。

因為每次調(diào)用get時,my_dict.get('john', default_value.copy())都會創(chuàng)建一個默認dict的副本(即使當(dāng)出現(xiàn)并返回'john'時),所以使用此try/except選項更快也非常好:

try:

return my_dict['john']

except KeyError:

return {'surname': '', 'age': 0}

或者,您也可以使用defaultdict:

import collections

def default_factory():

return {'surname': '', 'age': 0}

my_dict = collections.defaultdict(default_factory)

總結(jié)

以上是生活随笔為你收集整理的python dict get 怎么实现的_关于python:dict.get()方法返回一个指针的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。