在将函数用作字典的元素之前,是否必须正式定义函数?
def my_func():
print 'my_func'
d = {
'function': my_func
}
我宁愿定义内联函数。我只是尝试输入我想要做的事情,但是python语法的空白策略使得在dict中定义内联函数变得非常困难。有没有办法做到这一点?
答案 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的原因
一起使用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)
通过这种方式,您可以获得与“内联”相同的逻辑分组。