实现选择标志的 Pythonic 方式
Pythonic way to implement a selection flag
我在一个 Python 模块上工作,其中超过 3/4 的函数提供了 6 个选项的选择,并且相应地表现不同。1
我的目标是使这个参数的使用尽可能简单、明显和可读,以及(尽管不太重要)它的实现。
实现这样一个标志的最pythonic方式是什么?
在我看来,我有 3 个选择:
1.为每个组件使用字符串标识符(当前解决方案):
+:使用简单易读,无需额外导入,classes,实现细节
-:字符串比较,不灵活,用户必须知道字符串(没有编辑器帮助)
# 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: 使用枚举 class:
+:封闭的文字定义,比常量更明显的用法,更好的编辑器提示,类型提示
-:比字符串标识符更模糊的实现、模块依赖、更多的导入和对象
# 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的x、y、z分量和B场。由于各种原因,矢量实施将无法正常工作。
这很有趣,因为我喜欢谈论代码风格。我不知道你到底想做什么,但它似乎以一种简洁的方式实现 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)
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)
我在一个 Python 模块上工作,其中超过 3/4 的函数提供了 6 个选项的选择,并且相应地表现不同。1
我的目标是使这个参数的使用尽可能简单、明显和可读,以及(尽管不太重要)它的实现。
实现这样一个标志的最pythonic方式是什么?
在我看来,我有 3 个选择:
1.为每个组件使用字符串标识符(当前解决方案):
+:使用简单易读,无需额外导入,classes,实现细节
-:字符串比较,不灵活,用户必须知道字符串(没有编辑器帮助)
# 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: 使用枚举 class:
+:封闭的文字定义,比常量更明显的用法,更好的编辑器提示,类型提示
-:比字符串标识符更模糊的实现、模块依赖、更多的导入和对象
# 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的x、y、z分量和B场。由于各种原因,矢量实施将无法正常工作。
这很有趣,因为我喜欢谈论代码风格。我不知道你到底想做什么,但它似乎以一种简洁的方式实现 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)
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)