Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 字典和默认值_Python_Dictionary_Coding Style - Fatal编程技术网

Python 字典和默认值

Python 字典和默认值,python,dictionary,coding-style,Python,Dictionary,Coding Style,假设connectionDetails是一本Python字典,那么像这样重构代码的最好、最优雅、最“pythonic”的方法是什么 if "host" in connectionDetails: host = connectionDetails["host"] else: host = someDefaultValue 像这样: host = connectionDetails.get('host', someDefaultValue) 对于多个不同的默认值,请尝试以下操作:

假设
connectionDetails
是一本Python字典,那么像这样重构代码的最好、最优雅、最“pythonic”的方法是什么

if "host" in connectionDetails:
    host = connectionDetails["host"]
else:
    host = someDefaultValue
像这样:

host = connectionDetails.get('host', someDefaultValue)

对于多个不同的默认值,请尝试以下操作:

connectionDetails = { "host": "www.example.com" }
defaults = { "host": "127.0.0.1", "port": 8080 }

completeDetails = {}
completeDetails.update(defaults)
completeDetails.update(connectionDetails)
completeDetails["host"]  # ==> "www.example.com"
completeDetails["port"]  # ==> 8080
虽然
.get()
是一个很好的习惯用法,但它比
if/else
慢(如果大部分时间都可以预期字典中存在键,则比
try/except
慢):

您也可以使用类似的方法:

您可以传递任何普通函数而不是lambda:

from collections import defaultdict
def a():
  return 4

b = defaultdict(a, key="some_value")
b['absent'] => 4
b['key'] => "some_value"

python字典中有一种方法可以做到这一点:
dict.setdefault

connectionDetails.setdefault('host',someDefaultValue)
host = connectionDetails['host']
但是,如果尚未定义key
host
,则此方法会将
connectionDetails['host']
的值设置为
someDefaultValue
,这与所问问题不同。

(这是一个迟来的答案)

另一种方法是对
dict
类进行子类化并实现该方法,如下所示:

class ConnectionDetails(dict):
    def __missing__(self, key):
        if key == 'host':
            return "localhost"
        raise KeyError(key)
示例:

>>> connection_details = ConnectionDetails(port=80)

>>> connection_details['host']
'localhost'

>>> connection_details['port']
80

>>> connection_details['password']
Traceback (most recent call last):
  File "python", line 1, in <module>
  File "python", line 6, in __missing__
KeyError: 'password'
连接详细信息=连接详细信息(端口=80) >>>连接详细信息['host'] “本地主机” >>>连接详细信息[“端口”] 80 >>>连接详细信息['password'] 回溯(最近一次呼叫最后一次): 文件“python”,第1行,在 文件“python”,第6行,缺少__ KeyError:“密码”
测试@Tim Pietzcker对PyPy(5.2.0-alpha0)中Python3.3.5的情况的怀疑,我发现
.get()
if
/
else
两种方法的性能确实相似。实际上,在if/else情况下,如果条件和赋值涉及同一个键,则似乎只有一个查找(与上一种情况相比,其中有两个查找)


可以将lamba函数用作一个线性函数。创建一个新对象
connectionDetails2
,该对象可以像函数一样访问

connectionDetails2 = lambda k: connectionDetails[k] if k in connectionDetails.keys() else "DEFAULT"
现在使用

connectionDetails2(k)
而不是

connectionDetails[k]

如果
k
在键中,则返回字典值,否则返回
“DEFAULT”

注意,第二个参数是一个值,不是键。+1表示可读性,但
if/else
要快得多。这可能起作用,也可能不起作用。@Tim,你能提供一个参考,说明为什么
如果/else
更快吗?@Tim:我认为使用更高级语言的优点之一是解释器能够“看到”函数内部并对其进行优化,用户不必再进行微优化。这不是JIT编译的目的吗?@nishantjr:Python(至少是最常见的CPython变体)没有JIT编译。PyPy确实可以更快地解决这个问题,但我还没有安装它,因为到目前为止,标准Python的速度一直足够快。一般来说,这在现实生活中不太重要——如果需要进行时间关键型的数字运算,Python可能不是首选语言……我仍然不明白为什么
if/then
会更快。这两种情况都需要字典查找,除非调用
get()
的速度慢得多,否则还有什么原因导致速度慢?@Jens:函数调用很昂贵。在一个人口稠密的字典中,这应该不是什么大问题,对吗?这意味着,如果实际查找成本很高,那么函数调用将不会有多大影响。它可能只在玩具示例中起作用。@zehelvion:字典查找是
O(1)
,与字典大小无关,因此函数调用开销是相关的。如果调用函数的开销会让您决定不使用get,这是很奇怪的。使用您的团队成员最了解的方法。我来这里是为了一些不同于OP问题的问题,而您的解决方案正好解决了它。我会+1它,但遗憾的是它不适合
get
或类似的方法。这个答案对我很有用,可以确保添加到字典中的内容包括默认键。我的实现有点太长,无法在StackOverflow答案中描述,所以我在这里写了它。请注意,
setdefault()
返回值,因此它也可以工作:
host=connectionDetails.setdefault('host',someDefaultValue)
。请注意,如果该键以前不存在,它会将
connectionDetails['host']
设置为默认值。这是一个很好的惯用解决方案,但存在一个陷阱。如果connectionDetails随
None
一起提供,或将emptyString作为键值对中的一个值提供,则可能会出现意外结果。
默认值
字典可能会无意中删除其中一个值。(另请参见)我对您投了赞成票,但您的解决方案的问题是dicts与[]一起工作,而lambdas与()一起工作
connectionDetails2 = lambda k: connectionDetails[k] if k in connectionDetails.keys() else "DEFAULT"
connectionDetails2(k)
connectionDetails[k]