在Python中,如何仅存储一次函数的“常量”?

16 投票
4 回答
7822 浏览
提问于 2025-04-17 19:36

有些函数需要使用“常量”值(也就是说,这些值不打算在后面重新定义),而且这些值不应该作为参数传入。虽然默认参数对于每个函数只存储一次,但有些值作为参数传入并没有太大意义(也就是说,它们不应该成为函数的“签名”部分)。举个(不太有用的)例子:

def foo(bar):
    my_map = {"rab": barType, "oof": fooType}
    return my_map.get(bar,defaultType)()

每次调用时重新定义这样的常量会浪费CPU时间和内存空间。还有其他方法可以存储这些常量,比如把它们作为模块级的全局变量,或者把函数做成一个可调用的类,但可能还有其他方法,对吧?

当使用模块级全局变量的方法时,我会在我的(本意是)常量变量前加一个“_”,以表明它并不是为了让其他人使用。不过,我还是觉得模块的命名空间有点“污染”,更不用说使用一些像全局变量这样被不鼓励的东西的“羞耻”了:

_my_map = {"rab": barType, "oof": fooType}
def foo(bar):
    return _my_map.get(bar,defaultType)()

或者使用把它变成一个类的方法。我把__call__设为一个类方法,这样就不需要创建实例了:

class foo:
   my_map = {"rab": barType, "oof": fooType}
   @classmethod
   def __call__(cls,bar):
       return cls.my_map.get(bar,defaultType)()

这些解决方案够“Pythonic”吗?

还有其他方法可以做到这一点吗?

使用这样的“常量”作为一种实践是否合适?

注意:我例子中的这些对象不一定是真正的常量,但根据它们的用途可以被视为常量。

4 个回答

3

你还可以使用闭包:

def make_foo():
    my_map = {"rab": barType, "oof": fooType}
    def foo(bar):
        return my_map.get(bar,defaultType)()
    return foo
foo = make_foo()
6

在我看来,模块级别的常量是没有问题的。

根据PEP 8的规定,常量应该全部用大写字母,比如这样:

_MY_MAP = {"rab": barType, "oof": fooType}
def foo(bar):
    return _MY_MAP.get(bar,defaultType)()

标准库中的正则表达式模块就使用这种风格,很多知名的第三方库也是这样做的。如果你还不相信,可以去你的site-packages目录看看,使用grep命令搜索一下:

egrep "^_?[A-Z]+ =" *
18

把它设置为一个函数的属性

def foo(bar):
    return foo.my_map.get(bar, defaultType)()
foo.my_map = {"rab": barType, "oof": fooType}

我觉得可调用的类或者闭包太复杂了。

撰写回答