Python:将标志传递给函数

10 投票
6 回答
48158 浏览
提问于 2025-04-16 23:26

我一直在想,怎么才能最好的方式把标志(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

你可以把 flag1flagN 定义为全局变量,然后用 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,这样在需要改回去的时候就不用重新输入长名字了

撰写回答