最近,我在网上看到了一些关于如何在Python中没有好的“切换/案例”等问题的讨论。我意识到有几种方法可以做类似的事情 - 一些是lambda,一些是字典。关于替代方案,还有其他StackOverflow讨论。甚至有两个PEP(PEP 0275和PEP 3103)讨论(并拒绝)将开关/案例整合到语言中。
我提出了我认为切换/案例的优雅方式。
最终看起来像这样:
from switch_case import switch, case # note the import style
x = 42
switch(x) # note the switch statement
if case(1): # note the case statement
print(1)
if case(2):
print(2)
if case(): # note the case with no args
print("Some number besides 1 or 2")
所以,我的问题是:这是一个有价值的创作吗?你对改善它有什么建议吗?
我放了include file on github以及大量的例子。 (我认为整个包含文件大约有50行可执行文件,但我有1500行示例和文档。)我是否过度设计了这个东西,浪费了大量时间,还是有人觉得这样做有价值?
编辑:
试图解释为什么这与其他方法不同:
1)可以有多条路径(执行两种或更多种情况),
这在词典方法中比较难
2)可以检查“等于”以外的比较
(例如案例(less_than(1000))
3)比字典方法更可读,并且可能是/ elif方法
4)可以跟踪有多少真实案例
5)可以限制允许的真实案例数量。 (即执行
前2个......的真实案例
6)允许默认情况。
这是一个更详细的例子:
from switch_case import switch, case, between
x=12
switch(x, limit=1) # only execute the FIRST True case
if case(between(10,100)): # note the "between" case Function
print ("%d has two digits."%x)
if case(*range(0,100,2)): # note that this is an if, not an elif!
print ("%d is even."%x) # doesn't get executed for 2 digit numbers,
# because limit is 1; previous case was True.
if case():
print ("Nothing interesting to say about %d"%x)
# Running this program produces this output:
12 has two digits.
以下是一个示例,试图说明switch_case如何比传统的if / else更清晰简洁:
# conventional if/elif/else:
if (status_code == 2 or status_code == 4 or (11 <= status_code < 20)
or status_code==32):
[block of code]
elif status_code == 25 or status_code == 45:
[block of code]
if status_code <= 100:
[block can get executed in addition to above blocks]
# switch_case alternative (assumes import already)
switch(status_code)
if case (2, 4, between(11,20), 32): # significantly shorter!
[block of code]
elif case(25, 45):
[block of code]
if case(le(100)):
[block can get executed in addition to above blocks]
如果同一个开关一遍又一遍地重复,则可以节省很多时间。不确定用例的频繁程度,但似乎某些情况下这是有道理的。
github上的示例文件有更多示例。
答案 0 :(得分:6)
所以,我的问题是:这是一个有价值的创作吗?
没有
你对改善它有什么建议吗?
是。不要打扰。它节省了什么?真的吗?通过从每个x
条件中删除变量elif
,您实际上已经使代码更多变得模糊。另外,通过将elif
替换为if
你已经为所有Python程序员创建了故意混淆,他们现在认为这些案例是独立的。
这会造成混乱。
如果同一个开关一遍又一遍地重复,则可以节省很多时间。不确定用例的频繁程度,但似乎某些情况下这是有道理的。
没有。这是非常罕见的,非常人为的,非常难以阅读。查看所涉及的实际变量至关重要。删除变量名会使事情有意混淆。现在我必须找到拥有switch()
函数来解释case
。
当有两个或更多变量时,这会完全崩溃。
答案 1 :(得分:4)
在Stackoverflow上有过多的讨论可以解决这个问题。您可以使用顶部的搜索功能查找其他一些讨论。
但是,我没有看到你的解决方案比基本词典更好:
def switch(x):
return {
1 : 1,
2 : 2,
}[x]
虽然使用此方法添加默认子句并非易事。但是,您的示例似乎仍然复制了复杂的if / else语句?不确定我是否会包含一个外部库。
答案 2 :(得分:4)
恕我直言,switch statement存在的主要原因是它可以被翻译/编译成(非常快)jump table。您提议的实施将如何实现这一目标?正如其他海报所展示的那样,今天Python的词典就是这样做的。
其次,我认为switch语句可能比某些语言中的替代语言更清晰,但在python的情况下,我认为if
/ elif
/ else
在清晰度上获胜。
答案 3 :(得分:3)
我一直只是使用词典,if / elses或lambdas来表示我的切换语句。阅读你的代码tho =)
<强>文档:强>
答案 4 :(得分:3)
from pyswitch import Switch # pyswitch can be found on PyPI
myswitch = Switch()
@myswitch.case(42)
def case42(value):
print "I got 42!"
@myswitch.case(range(10))
def caseRange10(value):
print "I got a number from 0-9, and it was %d!" % value
@myswitch.caseIn('lo')
def caseLo(value):
print "I got a string with 'lo' in it; it was '%s'" % value
@myswitch.caseRegEx(r'\b([Pp]y\w)\b')
def caseReExPy(matchOb):
print r"I got a string that matched the regex '\b[Pp]y\w\b', and the match was '%s'" % matchOb.group(1)
@myswitch.default
def caseDefault(value):
print "Hey, default handler here, with a value of %r." % value
myswitch(5) # prints: I got a number from 0-9, and it was 5!
myswitch('foobar') # prints: Hey, default handler here, with a value of foobar.
myswitch('The word is Python') # prints: I got a string that matched the regex '\b[Pp]y\w\b', and the match was 'Python'
你明白了。为什么?是的,调度表是Python的发展方向。我只是厌倦了一遍又一遍地写它们,所以我写了一个类和一些装饰来为我处理它。
答案 5 :(得分:0)
2021 年更新:match-case
在 Python 3.10 中引入
这个激烈争论的话题现在可以结束了。
事实上,将在 Python 3.10 发布的 October 2021 引入了 structural pattern matching,它为语言带来了 match-case
构造。
有关详细信息,请参阅 this related answer。