如何使用内联函数声明字典

时间:2012-01-14 17:55:57

标签: python

在将函数用作字典的元素之前,是否必须正式定义函数?

def my_func():
  print 'my_func'

d = {
  'function': my_func
}

我宁愿定义内联函数。我只是尝试输入我想要做的事情,但是python语法的空白策略使得在dict中定义内联函数变得非常困难。有没有办法做到这一点?

7 个答案:

答案 0 :(得分:16)

答案似乎是没有办法在python中声明函数内联字典定义。感谢所有花时间做出贡献的人。

答案 1 :(得分:6)

你真的需要一本字典,还是getitem访问?

如果是后者,那么使用一个类:

>>> class Dispatch(object):
...     def funcA(self, *args):
...         print('funcA%r' % (args,))
...     def funcB(self, *args):
...         print('funcB%r' % (args,))
...     def __getitem__(self, name):
...         return getattr(self, name)
... 
>>> d = Dispatch()
>>> 
>>> d['funcA'](1, 2, 3)
funcA(1, 2, 3)

答案 2 :(得分:4)

考虑使用lambdas,但请注意lambdas 必须函数且不能包含语句(请参阅http://docs.python.org/reference/expressions.html#lambda

e.g。

d = { 'func': lambda x: x + 1 }
# call d['func'](2) will return 3

另请注意,在python2中,print不是函数。所以你必须做任何一件事:

from __future__ import print_function

d = {
    'function': print
}

或使用sys.stdout.write代替

d = {
    'function': sys.stdout.write
}

答案 3 :(得分:4)

您可以use a decorator

func_dict = {}

def register(func):
    func_dict[func.__name__] = func
    return func

@register
def a_func():
    pass

@register
def b_func():
    pass

func_dict将最终使用该函数的全名进行映射:

>>> func_dict
{'a_func': <function a_func at 0x000001F6117BC950>, 'b_func': <function b_func at 0x000001F6117BC8C8>}

您可以根据需要修改register使用的密钥。诀窍是我们使用函数的__name__属性来获取适当的字符串。

答案 4 :(得分:3)

有些函数可以使用lambda表达式匿名“内联”,例如:

>>> d={'function': lambda x : x**2}
>>> d['function'](5)
25

但是对于任何半复杂的(或使用语句),您可能应该事先定义它们。

答案 5 :(得分:3)

没有充分的理由想在Python中使用字典来编写它。这很奇怪,并不是命名空间函数的常用方法。

这里适用的Python哲学是:

  

应该有一个 - 最好只有一个 - 显而易见的方法。

结合

  

可读性计数。

这样做也会使典型的Python用户难以理解和阅读。

在这种情况下,字典的好处是将字符串映射到函数并将它们命名为字典,但这个功能已经由模块和类提供,熟悉Python的人更容易理解。

示例:

模块方法:

#cool.py

def cool():
    print 'cool'

现在使用模块,就像使用你的dict一样:

import cool
#cool.__dict__['cool']()
#update - to the more correct idiom vars
vars(cool)['cool']()

班级方法:

class Cool():
    def cool():
        print 'cool'

#Cool.__dict__['cool']()
#update - to the more correct idiom vars
vars(Cool)['cool']()

在以下评论后进行修改:

argparse似乎非常适合这个问题,所以你不必重新发明轮子。如果你决定自己完全实现它,虽然argparse源应该给你一些好的方向。无论如何,下面的部分似乎适用于这个用例:

  

15.4.4.5。超越sys.argv

     

有时使用ArgumentParser解析参数可能很有用   除了sys.argv之外。这可以通过传递一个   parse_args()的字符串列表。这对于测试非常有用   互动提示:

     

15.4.5.1。子commands¶

     

ArgumentParser.add_subparsers()

     

许多程序将其功能分解为多个子命令,例如,svn程序可以调用子命令   比如svn checkout,svn update和svn commit。

     

15.4.4.6。命名空间对象

     

让ArgumentParser赋值属性也可能很有用   已存在的对象,而不是新的Namespace对象。这个   可以通过指定namespace = keyword参数来实现:

更新,这是使用argparse

的示例
strategizer = argparse.ArgumentParser()
strat_subs = strategizer.add_subparsers()
math = strat_subs.add_parser('math')
math_subs = math.add_subparsers()
math_max = math_subs.add_parser('max')
math_sum = math_subs.add_parser('sum')
math_max.set_defaults(strategy=max)
math_sum.set_defaults(strategy=sum)

strategizer.parse_args('math max'.split())
Out[46]: Namespace(strategy=<built-in function max>)

strategizer.parse_args('math sum'.split())
Out[47]: Namespace(strategy=<built-in function sum>)

我想说明我推荐argparse的原因

  1. 主要要求使用表示选项和子选项的字符串映射到函数。
  2. 这很简单(在通过功能填充的argparse模块之后)。
  3. 使用Python标准库模块。这让其他熟悉Python的人在没有深入了解实现细节的情况下了解了你的工作,并且对那些没有深入了解的人有很好的文档记录。
  4. 可以利用开箱即用的许多额外功能(不是最好的理由!)。
  5. 一起使用argparse和策略模式

    对于战略模式的简单实施,这已经得到了很好的回答。

    How to write Strategy Pattern in Python differently than example in Wikipedia?

    #continuing from the above example
    class MathStudent():
        def do_math(self, numbers):
            return self.strategy(numbers)
    
    
    maximus = strategizer.parse_args('math max'.split(),
                                      namespace=MathStudent())
    
    sumera = strategizer.parse_args('math sum'.split(),
                                     namespace=MathStudent())
    
    maximus.do_math([1, 2, 3])
    Out[71]: 3
    
    sumera.do_math([1, 2, 3])
    Out[72]: 6
    

答案 6 :(得分:2)

内联函数的要点是模糊字典和类实例之间的区别。例如,在javascript中,这种技术使得编写几乎没有可重用性的控件类非常愉快。此外,非常有用的API然后符合众所周知的字典协议,是自我解释(双关语)。

你可以在python中做到这一点 - 它看起来不像字典!实际上,你可以在任何范围内使用class关键字(即函数中的类def,或类def中的类def),它的子项可以是你正在寻找的dictonary;只需检查定义的属性,就好像它是一个javascript词典。

示例好像是真的:

somedict = {
    "foo":5,
    "one_function":your method here,
    "two_function":your method here,
}

实际上是以

完成的
class somedict:
    foo = 5
    @classmethod
    def one_method(self):
        print self.foo
        self.foo *= 2;

    @classmethod
    def two_method(self):
        print self.foo

这样你就可以说:

somedict.foo          #(prints 5)
somedict.one_method() #(prints 5)
somedict.two_method() #(prints 10)

通过这种方式,您可以获得与“内联”相同的逻辑分组。