如何将一系列条件映射为字典中的键?
How to map a series of conditions as keys in a dictionary?
我知道您可以使用字典来替代 switch 语句,如下所示:
def printMessage(mystring):
# Switch statement without a dictionary
if mystring == "helloworld":
print "say hello"
elif mystring == "byeworld":
print "say bye"
elif mystring == "goodafternoonworld":
print "good afternoon"
def printMessage(mystring):
# Dictionary equivalent of a switch statement
myDictionary = {"helloworld": "say hello",
"byeworld": "say bye",
"goodafternoonworld": "good afternoon"}
print myDictionary[mystring]
但是,如果使用条件,除了等式 (==) 之外 return true of false 这些不能轻易映射,即:
if i > 0.5:
print "greater than 0.5"
elif i == 5:
print "it is equal to 5"
elif i > 5 and i < 6:
print "somewhere between 5 and 6"
以上不能直接转换为字典键值对:
# this does not work
mydictionary = { i > 0.5: "greater than 0.5" }
可以使用 lambda,因为它是可哈希的,但从映射中获取结果字符串的唯一方法是将相同的 lambda 对象传递到字典中,而不是在 lambda 的计算结果为真时:
x = lambda i: i > 0.5
mydictionary[x] = "greater than 0.5"
# you can get the string by doing this:
mydictionary[x]
# which doesnt result in the evaluation of x
# however a lambda is a hashable item in a dictionary
mydictionary = {lambda i: i > 0.5: "greater than 0.5"}
有谁知道在 lambda 求值和 return 值之间创建映射的技术或方法?
(这可能类似于函数式语言中的模式匹配)
您的条件在本质上是连续的;你想一个接一个地测试,而不是在这里将少量键映射到一个值。改变条件的顺序可能会改变结果; 5
的值会导致样本中的 "greater than 0.5"
,而不是 "it is equal to 5"
。
使用元组列表:
myconditions = [
(lambda i: i > 0.5, "greater than 0.5"),
(lambda i: i == 5, "it is equal to 5"),
(lambda i: i > 5 and i < 6, "somewhere between 5 and 6"),
]
之后您可以依次访问每一个,直到有一个匹配:
for test, message in myconditions:
if test(i):
return message
重新排序测试将改变结果。
字典适用于您的第一个示例,因为有一个简单的等式测试 针对由字典优化的多个静态值,但这里没有这样简单的等式。
您不能使用字典来映射任意条件,因为多个条件可能同时为真。相反,您需要按顺序评估每一个,并在第一次遇到真正的代码时执行关联的代码。这是一种正式实施类似方法的概述,它甚至允许相当于 default:
案例。
from collections import namedtuple
Case = namedtuple('Case', ['condition', 'code'])
cases = (Case('i > 0.5',
"""print 'greater than 0.5'"""),
Case('i == 5',
"""print 'it is equal to 5'"""),
Case('i > 5 and i < 6',
"""print 'somewhere between 5 and 6'"""))
def switch(cases, **namespace):
for case in cases:
if eval(case.condition, namespace):
exec(case.code, namespace)
break
else:
print 'default case'
switch(cases, i=5)
输出:
greater than 0.5
没有直接关系,但我经常使用类似于下面示例的范例,用 dictionaruy 查找替换级联 ifs。
def multipleifs(a=None,b=None,c=None,d=None,e=None):
""" Func1 with cascaded if
>>> multipleifs(10,20,30,40,50)
160
"""
x=10
if a:
x += 10
if b:
x += 20
if c:
x += 30
if d:
x += 40
if e:
x += 50
return x
def dictif(a=None,b=None,c=None,d=None,e=None):
""" Func2 with dictionary replacing multiple ifs
>>> dictif(10,20,30,40,50)
160
"""
x, mydict = 10, dict(enumerate([10,20,30,40,50]))
for count, item in enumerate([a,b,c,d,e]):
if item: x += mydict.get(count,0)
return x
我知道您可以使用字典来替代 switch 语句,如下所示:
def printMessage(mystring):
# Switch statement without a dictionary
if mystring == "helloworld":
print "say hello"
elif mystring == "byeworld":
print "say bye"
elif mystring == "goodafternoonworld":
print "good afternoon"
def printMessage(mystring):
# Dictionary equivalent of a switch statement
myDictionary = {"helloworld": "say hello",
"byeworld": "say bye",
"goodafternoonworld": "good afternoon"}
print myDictionary[mystring]
但是,如果使用条件,除了等式 (==) 之外 return true of false 这些不能轻易映射,即:
if i > 0.5:
print "greater than 0.5"
elif i == 5:
print "it is equal to 5"
elif i > 5 and i < 6:
print "somewhere between 5 and 6"
以上不能直接转换为字典键值对:
# this does not work
mydictionary = { i > 0.5: "greater than 0.5" }
可以使用 lambda,因为它是可哈希的,但从映射中获取结果字符串的唯一方法是将相同的 lambda 对象传递到字典中,而不是在 lambda 的计算结果为真时:
x = lambda i: i > 0.5
mydictionary[x] = "greater than 0.5"
# you can get the string by doing this:
mydictionary[x]
# which doesnt result in the evaluation of x
# however a lambda is a hashable item in a dictionary
mydictionary = {lambda i: i > 0.5: "greater than 0.5"}
有谁知道在 lambda 求值和 return 值之间创建映射的技术或方法? (这可能类似于函数式语言中的模式匹配)
您的条件在本质上是连续的;你想一个接一个地测试,而不是在这里将少量键映射到一个值。改变条件的顺序可能会改变结果; 5
的值会导致样本中的 "greater than 0.5"
,而不是 "it is equal to 5"
。
使用元组列表:
myconditions = [
(lambda i: i > 0.5, "greater than 0.5"),
(lambda i: i == 5, "it is equal to 5"),
(lambda i: i > 5 and i < 6, "somewhere between 5 and 6"),
]
之后您可以依次访问每一个,直到有一个匹配:
for test, message in myconditions:
if test(i):
return message
重新排序测试将改变结果。
字典适用于您的第一个示例,因为有一个简单的等式测试 针对由字典优化的多个静态值,但这里没有这样简单的等式。
您不能使用字典来映射任意条件,因为多个条件可能同时为真。相反,您需要按顺序评估每一个,并在第一次遇到真正的代码时执行关联的代码。这是一种正式实施类似方法的概述,它甚至允许相当于 default:
案例。
from collections import namedtuple
Case = namedtuple('Case', ['condition', 'code'])
cases = (Case('i > 0.5',
"""print 'greater than 0.5'"""),
Case('i == 5',
"""print 'it is equal to 5'"""),
Case('i > 5 and i < 6',
"""print 'somewhere between 5 and 6'"""))
def switch(cases, **namespace):
for case in cases:
if eval(case.condition, namespace):
exec(case.code, namespace)
break
else:
print 'default case'
switch(cases, i=5)
输出:
greater than 0.5
没有直接关系,但我经常使用类似于下面示例的范例,用 dictionaruy 查找替换级联 ifs。
def multipleifs(a=None,b=None,c=None,d=None,e=None):
""" Func1 with cascaded if
>>> multipleifs(10,20,30,40,50)
160
"""
x=10
if a:
x += 10
if b:
x += 20
if c:
x += 30
if d:
x += 40
if e:
x += 50
return x
def dictif(a=None,b=None,c=None,d=None,e=None):
""" Func2 with dictionary replacing multiple ifs
>>> dictif(10,20,30,40,50)
160
"""
x, mydict = 10, dict(enumerate([10,20,30,40,50]))
for count, item in enumerate([a,b,c,d,e]):
if item: x += mydict.get(count,0)
return x