Python:将标志传递给函数
我一直在想,怎么才能最好的方式把标志(flags)传给Python函数。最简单的方法就是这样:
def func(data, flag1, flag2, flag3):
...
func(my_data, True, False, True)
这个写法简洁明了,但其实很难读懂,因为“True”或“False”并不能告诉你具体设置了哪个标志,而且你还得从左到右仔细数参数。你可以把它们改成关键字参数:
def func(data, flag1=False, flag2=False, flag3=False):
...
func(my_data, flag1=True, flag3=True)
但这样有点多余,因为“True”本身并没有什么特别的含义。我也可以把它作为一个列表传入:
func(mydata, ['flag1', 'flag3'])
或者
func(mydata, [func.flag1, func.flag3])
不过第一个方法感觉不太好,因为用字符串作为标志,而第二个方法还是有点重复。理想情况下,我想要的写法是:
func(my_data, flag1, flag3)
这样可以以最少的冗余和啰嗦的方式把标志传给函数。在Python中有没有办法做到这样的呢?
编辑:最后我选择了:
func(mydata, flagA=1, flagB=1)
主要是因为之前提到的原因:编译时检查(而不是传字符串),没有命名空间污染(不像使用全局的“ENUM”),而且写起来的冗余也很少(=1或=0只需要2个字符,而=True或=False需要5或6个字符)。这也让设置标志的默认值变得非常简单:
def func(data, flagA=1, flagB=0, flagC=1):
...
这样写比起用**kwarg风格的标志来提取和赋值默认值要清晰得多,写起来也简单得多。标志基本上是静态检查的,写起来也很清晰干净。现在如果能再少掉最后两个字符就好了……
6 个回答
5
我怀念以前那些简单的位运算标志:
a = 1
b = 2
c = 4
d = 8
def func( data, flags ):
print( ( flags & a) == a )
print( ( flags & b) == b )
print( ( flags & c) == c )
print( ( flags & d) == d )
>>>> func("bla", a|c|d)
>>>> True
>>>> False
>>>> True
>>>> True
5
你可以把 flag1
到 flagN
定义为全局变量,然后用 func( *args)
来定义你的函数。
FLAG1 = 1
FLAG2 = 2
def func(*args):
pass
func(FLAG1, FLAG2)
通过单独定义这些标志,而不是用字符串,你可以避免在标志名称上出现拼写错误,这样在调试的时候就不会那么头疼了。
4
一些Python的标准库使用了这个方法:
re.match(pattern, str, re.MULTILINE | re.IGNORECASE)
你可以通过使用 *args 来调整这个方法:
my.func(a, b, c, my.MULTLINE, my.IGNORECASE)
我真的建议使用 flag1=True 的方式:
- 这样写很容易理解
- 标志的名字在编译时就会被检查(除非使用了 **kwargs)
- 你可以用 flag=1 和 flag=0 来代替 True 和 False,这样看起来更简洁
- 你可以临时把 LONG_FLAG_NAME_YOU_DONT_REMEMBER=True 改成 False,这样在需要改回去的时候就不用重新输入长名字了