16

某些函数需要不被参数化的“恒定”值(即不设计为以后重新定义)。虽然每个函数的默认参数只存储一次,但有些参数作为参数(即作为签名的一部分)并不是很有意义。对于(不是很有用的)示例:

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

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

在执行模块级全局方式时,我在我的(意为一个)常量变量前面加上一个“_”,以表明它符合任何人的兴趣。我仍然觉得模块命名空间有点“污染”,更不用说使用像全局变量这样不鼓励的东西的耻辱了

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

或者将其转换为类方式。我制作了__call__一个classmethod,以避免创建实例的需要:

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

这些解决方案是否足够pythonic?

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

使用这样的“常数”甚至可以作为一种做法吗?

请注意,我的示例中的这些对象不一定是实际常量,而是根据它们的目的使用(并且可以被认为是)。

4

4 回答 4

17

将其设置为函数的属性

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

IMO 可调用类或闭包不够简单。

于 2013-03-19T09:18:13.217 回答
5

恕我直言,模块级常量没有任何问题。

请注意,根据PEP 8,常量应该全部大写,如下所示:

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

标准库中的正则表达式模块使用这种风格,许多成熟的第三方库也是如此。如果您不相信,只需转到您的site-packages目录并 grep:

egrep "^_?[A-Z]+ =" *
于 2013-03-19T10:38:41.613 回答
3

你也可以使用闭包:

def make_foo():
    my_map = {"rab": barType, "oof": fooType}
    def foo(bar):
        return my_map.get(bar,defaultType)()
    return foo
foo = make_foo()
于 2013-03-19T09:18:21.387 回答
1

做一些尽可能独立的东西。您可以创建一个函数对象(又名functor)类并给它一个__call__()方法一个classmethod(但可能不是两者):

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")

另一种选择是定义 a staticmethod,我不会说明它,因为它与其他两个非常相似——但你明白我希望的想法。

于 2013-03-19T12:06:30.203 回答