- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
dict.setdefault
的一个小烦恼是它总是评估它的第二个参数(当然,当给定时),即使第一个参数已经是字典中的键。
例如:
import random
def noisy_default():
ret = random.randint(0, 10000000)
print 'noisy_default: returning %d' % ret
return ret
d = dict()
print d.setdefault(1, noisy_default())
print d.setdefault(1, noisy_default())
这会产生如下输出:
noisy_default: returning 4063267
4063267
noisy_default: returning 628989
4063267
正如最后一行所确认的,noisy_default
的第二次执行是不必要的,因为此时 key 1
已存在于 d
中(值为 4063267
)。
是否可以实现 dict
的子类?谁的setdefault
方法懒惰地评估它的第二个参数?
编辑:
以下是受 BrenBarn 的评论和 Pavel Anossov 的回答启发的实现。在此过程中,我继续实现了 get 的惰性版本,因为基本思想基本相同。
class LazyDict(dict):
def get(self, key, thunk=None):
return (self[key] if key in self else
thunk() if callable(thunk) else
thunk)
def setdefault(self, key, thunk=None):
return (self[key] if key in self else
dict.setdefault(self, key,
thunk() if callable(thunk) else
thunk))
现在,片段
d = LazyDict()
print d.setdefault(1, noisy_default)
print d.setdefault(1, noisy_default)
产生这样的输出:
noisy_default: returning 5025427
5025427
5025427
注意 d.setdefault
的第二个参数上面现在是可调用的,而不是函数调用。
当第二个参数为LazyDict.get
或 LazyDict.setdefault
不是可调用的,它们的行为方式与相应的 dict
相同方法。
如果想要传递一个可调用对象作为默认值本身(即,不意味着要调用),或者如果要调用的可调用对象需要参数,请在前面加上 lambda:
到适当的论点。例如:
d1.setdefault('div', lambda: div_callback)
d2.setdefault('foo', lambda: bar('frobozz'))
那些不喜欢重写 get
的人和 setdefault
,和/或因此需要测试可调用性等,可以改用此版本:
class LazyButHonestDict(dict):
def lazyget(self, key, thunk=lambda: None):
return self[key] if key in self else thunk()
def lazysetdefault(self, key, thunk=lambda: None):
return (self[key] if key in self else
self.setdefault(key, thunk()))
最佳答案
这也可以通过 defaultdict
来完成。它使用可调用对象实例化,然后在访问不存在的元素时调用该对象。
from collections import defaultdict
d = defaultdict(noisy_default)
d[1] # noise
d[1] # no noise
defaultdict
的警告是可调用对象没有参数,因此您不能像使用 dict.setdefault
那样从键中派生默认值。这可以通过在子类中覆盖 __missing__
来缓解:
from collections import defaultdict
class defaultdict2(defaultdict):
def __missing__(self, key):
value = self.default_factory(key)
self[key] = value
return value
def noisy_default_with_key(key):
print key
return key + 1
d = defaultdict2(noisy_default_with_key)
d[1] # prints 1, sets 2, returns 2
d[1] # does not print anything, does not set anything, returns 2
有关详细信息,请参阅 collections模块。
关于python - 如何实现惰性 setdefault?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17532929/
我有以下代码片段: mirna2age = {} for i in agesdb: mirna2age.setdefault(i[0],default=[]).append(i[1]) 但是,
TimeZone.setDefault 时区似乎不支持夏令时。如果我保留默认值(不使用函数 setDefault),应用程序将显示 EST/EDT 中的日期。但如果我想更改时区(我使用 TimeZon
给出以下通用代码: def soapQuery(): soapuser = "Base64String" soappass = "Base64String" soapurl =
这个问题已经有答案了: python dict setdefault, confused (3 个回答) 已关闭 6 年前。 有人可以解释一下在下面的情况下如何对字典“inverse”进行赋值吗? d
dict.setdefault 的一个小烦恼是它总是评估它的第二个参数(当然,当给定时),即使第一个参数已经是字典中的键。 例如: import random def noisy_default():
这是来自 Django's authentification models 的一段代码(用户经理): def create_superuser(self, username, email, passw
我的应用程序用户可以从应用程序的设置页面更改应用程序语言,因此我使用 Resources.updateConfiguration() 开发它。和 Context.createConfiguration
这是来自 Django's authentification models 的一段代码(用户经理): def create_superuser(self, username, email, passw
我想在 Java 小程序中进行简单的 HTTP 身份验证,我正在尝试这种方式: static class MyAuthenticator extends Authenticator {
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我从 Automate the boring stuff with Python 一书中得到这段代码,但我不明白 setdefault() 方法如何计算唯一字符的数量。 代码: message = '
我想知道是否有一种方法可以使用类似 lambda 的样式来附加到已排序的字典列表字段中。 示例: a = {} a.setdefault("foo", []).append(2) a.setdefau
这个问题在这里已经有了答案: Python list + list vs. list.append() (2 个答案) 关闭 7 年前。 我有下面的代码,我试图在输入中每次出现时将 1 append
为了说明这个问题,我创建了一个简单的例子: #!/usr/bin/env python class Person(): def __init__(self): self.cac
我一直在寻找一种算法,但我无法弄清楚为什么字典 d 中有值而 curr 中没有。我认为似乎没有对 dict d 做任何事情。 >>> def what(*words): ... d = {}
在 Python 2.5 中添加的 collections.defaultdict 大大减少了对 dict 的 setdefault 方法的需求。这个问题是针对我们的集体教育的: setdefault
我正在寻找一种更好的方法来设置 Java 的默认时区。我们当前正在访问 DB2 数据库以获取其当前时区,但它不是时区名称,只是当前的小时/分钟偏移值。因此,我们采用该值并构造一个类似“GMT-07:0
我正在使用 jQuery timepicker 插件来扩展 jQuery datepicker,它允许我有一个日期+时间选择器。 link to the addon 为了设置格式设置和区域设置等默认设
如果我有这样的声明: INSERT INTO foo (id, name, description, etc_a, etc_b) VALUES (?, ?, ?, ?, ?); 它被传递到 Prepa
使用集合时的常见模式如下: number_list = [1,5,7,2,4,4,1,3,8,5] number_set = set() for number in number_list: #
我是一名优秀的程序员,十分优秀!