我最近阅读了建议不要在支持它的语言中使用switch-case语句的问题.就Python而言,我已经看到了许多交换机案例替换,例如:
使用字典(许多变体)
使用元组
使用函数装饰器(http://code.activestate.com/recipes/440499/)
使用多态(推荐的方法而不是类型检查对象)
使用if-elif-else梯形图
有人甚至推荐了访客模式(可能是外在的)
鉴于选择的种类繁多,我在确定如何处理特定代码时遇到了一些困难.我想学习选择其中一种方法的标准.另外,我很感谢在我遇到麻烦的具体情况下做什么的建议(对选择的解释).
这是具体问题:
(1)
def _setCurrentCurve(self, curve): if curve == "sine": self.currentCurve = SineCurve(startAngle = 0, endAngle = 14, lineColor = (0.0, 0.0, 0.0), expansionFactor = 1, centerPos = (0.0, 0.0)) elif curve == "quadratic": self.currentCurve = QuadraticCurve(lineColor = (0.0, 0.0, 0.0))
响应于选择从菜单绘制曲线,该方法由qt-slot调用.一旦申请完成,上述方法将包含总共4-7条曲线.在这种情况下使用丢弃词典是否合理?由于最明显的方法是if-elif-else,我应该坚持下去吗?我也考虑在这里使用**kargs(有朋友的帮助)因为所有曲线类都使用**kargs ...
(2)
第二段代码是当用户改变曲线属性时调用的qt-slot.基本上,槽从gui(spinBox)获取数据并将其放入适当曲线类的实例变量中.在这种情况下,我再次有同样的问题 - 我应该使用dict吗?
这是前面提到的插槽 -
def propertyChanged(self, name, value): """A Qt slot, to react to changes of SineCurve's properties.""" if name == "amplitude": self.amplitude = value elif name == "expansionFactor": self.expansionFactor = value elif name == "startAngle": self.startAngle = value elif name == "endAngle": self.endAngle = value
供参考,以下是连接上述插槽的代码 -
def _connectToPage(self, page): for connectionData in page.getConnectibles(): self.connect(connectionData["object"], SIGNAL(connectionData["signal"]), lambda value, name = connectionData["property"]:\ self.currentCurve.propertyChanged(name, value)) self.connect(connectionData["object"], SIGNAL(connectionData["signal"]), self.hackedDisplayArea.update)
注 - self.endAngle等在构造函数中初始化.
据我所知,选择字典的原因是快速查找.什么时候有必要?当我有100个案件或更多?每次调用函数时,继续构建和丢弃字典是一个好主意吗?如果我在函数之外为此目的构建一个dict,我应该检查它是否需要在哪里?如果在其他地方不需要它会发生什么?
我的问题是,如果有最佳实践,最佳做法是什么?什么是最好/最优雅的方式?换句话说,何时使用if-elif-else,何时使用其他每个选项?
叹.对问题的错误部分过分绞尽脑汁.switch语句不是问题.表达"替代"的方法有很多,不能增加意义.
问题是意义 - 而不是技术陈述的选择.
有三种常见的模式.
将键映射到对象.如果字典几乎完全是静态的,那么请使用字典,并且您可以在简单键和另一个更复杂的键之间进行映射.每次需要时动态构建字典都是愚蠢的.如果它是你的意思,你可以使用它:你的"条件"是简单的,映射到对象的静态键值.
子类之间的变体行为.使用多态而不是类型检查对象.正确.如果在具有变体行为的多个类中有类似的对象,则它们应该是多态的.尽可能经常使用它.
其他变体行为.使用if-elif-else梯形图.如果没有很大的静态键值映射,请使用此选项.在条件复杂时使用此选项,或者您指的是过程,而不是对象.
其他一切都只是棘手的代码,可以达到类似的效果.
使用元组.这只是没有映射的字典.这需要搜索,应尽可能避免搜索.不要这样做,效率低下.使用字典.
使用函数装饰器(http://code.activestate.com/recipes/440499/).恶心.这隐瞒了你正在解决的问题的if-elif-elif性质.不要这样做,选择是排他性的并不明显.使用其他任何东西
有人甚至推荐了访客模式.如果有一个遵循Composite设计模式的对象,请使用此选项.这取决于多态性的工作,所以它并不是一个真正不同的解决方案.
在第一个例子中,我肯定会坚持使用if-else语句.事实上我没有理由不使用if-else除非
您发现(使用例如配置文件模块)if语句是一个瓶颈(非常不可能的IMO,除非您有大量的案例做得很少)
使用字典的代码更清晰/重复次数更少.
你的第二个例子我实际上会重写
setattr(self, name, value)
(可能添加一个断言语句来捕获无效名称).