global variables:在python中,如何存储常量?只对函数执行一次?

有些函数需要"常量"值(例如。不设计用于稍后重新定义),即不进行参数化。虽然每个函数的默认参数只存储一次,但是有些参数作为参数并没有太大的意义(例如。成为签名的一部分)。For (a not very useful)例子:

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

为每个调用重新定义这样一个常量会浪费CPU时间和RAM空间。其他一些方法是存储诸如模块级全局变量之类的常量,或者使函数成为可调用类,但是可能还有其他方法?

当执行模块级全局方法时,我在(表示为a)常量变量前面加上一个"_",以表明它不存在,不符合任何人的兴趣。尽管如此,我仍然觉得模块名称空间有点"受污染",更不用说使用像全局变量这样令人沮丧的东西了:

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

或者把它转换成类的方式。我将__call__作为一个类方法,以避免创建实例:

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

这些解够勾股定理吗?

还有其他方法吗?

作为一种实践,使用这样的"常量"可以吗?

注意,在我的示例中,这些对象不一定是实际的常量,但是它们的用途是这样使用的(并且可以这样认为)。


将其设置为函数的属性:

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

,

在我看来,可调用类或闭包不够简单。


依我之见,模块级常量没有什么问题。

注意,根据PEP8,常数应该都是大写的,就像这样:

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

标准库中的正则表达式模块使用这种风格,许多已建立的第三方库也使用这种风格。如果你不相信,就去你的site-packages目录和grep:

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


使之尽可能独立。您可以创建一个函数对象(又名函子)类,并给它一个__call__()方法或classmethod(但可能不是两者都有):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class bazType(object): pass
class barType(object): pass
class fooType(object): pass

class Foo(object):
    _DEFAULT_TYPE = bazType
    _MY_MAP = {"rab": barType,"oof": fooType}

    def __call__(self, bar):
        return self._MY_MAP.get(bar, self._DEFAULT_TYPE)()

    @classmethod
    def foo(cls, bar):
        return cls._MY_MAP.get(bar, cls._DEFAULT_TYPE)()

# using classmethod
print Foo.foo("rab")

# using __call__ method
foo = Foo()
print foo("baz")

# alternative way to use classmethod
foo = Foo.foo
print foo("oof")

另一种方法是定义一个staticmethod,我将不对此进行说明,因为它与其他两个非常相似——但是我希望您能理解我的意思。


你也可以使用闭包:

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