问题描述
我在一个python模块上工作,其中超过3/4的函数提供6个选项的选择,并且相应地表现不同。 1
我的目标是使此参数的使用尽可能简单,明显和易读,以及(虽然不那么重要)实现它。
实现这种标记的最Python方式是什么?
我看到的方式有3种选择:
1。为每个组件使用字符串标识符(当前解决方案):
+ :用法简单易读,没有其他导入,类,实现详细信息
-:字符串比较不灵活,用户必须知道字符串(没有编辑器帮助)
# in module/__init__.py
E_X = 'e_x'
E_Y = 'e_y'
...
# in module/whatever.py:
def do_sg(args,comp):
if comp == E_X:
set_some_state_for_ex()
res = calc_sg_with_ex(args)
elif comp == E_Y:
...
return res
# usage
from module.whatever import do_sg
res = do_sg(args,'e_r')
2:使用模块范围的常量:
+ :文字定义,编辑提示
-:使用更加晦涩难懂,名称空间受到污染(避免使用更晦涩的名称),没有容易的方法来导入所有组件
# in module/__init__.py
E_X_COMP = 1
E_Y_COMP = 2
...
# in module/whatever.py,implementation v1
from . import *
def do_sg(args,comp):
if comp == E_X_COMP:
set_some_state_for_e_x()
res = calc_sg_with_e_x(args)
elif comp == E_Y_COMP:
...
return res
# usage ( (1) may be used this way as well)
import module # or from module import E_X_COMP,E_Y_COMP,...
from module.whatever import do_sg
res = do_sg(args,module.E_X_COMP)
# or more obscurely:
res = do_sg(args,0)
3:使用Enum类:
+ :封闭的文字定义,比常量更明显的用法,更好的编辑器提示,类型提示
-:与字符串标识符相比,实现更模糊,模块依赖性更大,导入和对象更多
# in module/__init__.py
from enum import Enum
class component(Enum):
e_x = 1
e_y = 2
...
# in module/whatever.py,implementation v1
from . import component
def do_sg(args,comp):
if comp is component.e_x:
res = calc_sg_with_e_x(args)
elif comp is component.e_y:
...
return res
# usage
from module import component
from module.whatever import do_sg
res = do_sg(args,component.e_x)
4:其他选项?
还有其他我没有考虑的方法吗?
1:更具体地说,该模块用于计算电磁场的分量,并且可以选择要考虑的分量-可以是E和B场的x,y和z分量。向量实现由于各种原因而无法正常工作。
解决方法
Enum
正是针对此类问题而创建的。还应该将它们视为常量,因此适当的命名将有所帮助:
class Component(Enum):
E_X = 1
E_Y = 2
正在使用;
from module import Component
from module.whatever import do_sg
res = do_sg(args,Component.E_X)
,
这很有趣,因为我喜欢谈论代码样式。我不知道您确切想做什么,但是似乎以一种简洁的方式实现了switch
。如果您是我,则不会使用任何(global
)常量。它们总是使代码的可读性降低。
一种使代码更具可读性的方法,我认为您可以将if-else块定义为函数,并直接使用函数而不是使用外部作用域常量进行分支。例如:
# in module/whatever.py,implementation v1
from . import *
class do_sg:
@classmethod
def e_x(args):
set_some_state_for_e_x()
res = calc_sg_with_e_x(args)
return res
@classmethod
def e_y(args):
...
return res
# usage
from module.whatever import do_sg
res = do_sg.e_x(args)