有些函数需要"常量"值(例如。不设计用于稍后重新定义),即不进行参数化。虽然每个函数的默认参数只存储一次,但是有些参数作为参数并没有太大的意义(例如。成为签名的一部分)。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)() |
或者把它转换成类的方式。我将
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)() |
标准库中的正则表达式模块使用这种风格,许多已建立的第三方库也使用这种风格。如果你不相信,就去你的
1 | egrep"^_?[A-Z]+ =" * |
使之尽可能独立。您可以创建一个函数对象(又名函子)类,并给它一个
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") |
另一种方法是定义一个
你也可以使用闭包:
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() |