我正在编写命令行增强程序。我选择这样做而不是使用optparse
,argparse
或其他可用的,因为:1)我想要体验; 2)我不喜欢他们。 ;)
一个简单的例子:
@Script(
live_daemon=Spec('test the installed daemon', FLAG, None, remove=True),
verbose=Spec('more info on tests', FLAG),
port=Spec('port for daemon to use for mini-tcp server', OPTION, type=int, remove=True),
log=Spec('specific tests to log', MULTI, remove=True),
tests=Spec('specific tests to run', OPTION),
)
def main(live_daemon, verbose, log, port=8079, *tests):
pass
从上面的port
选项中可以看出,可以指定将传递给函数的参数的类型;默认类型为str
,但允许任何可调用。
上述示例中未显示的一种可能性是映射:
@Script( random_vars=('for example', OPTION, type=(str, int)) )
def main(**random_vars):
pass
此实用程序的内容是将传入参数转换为默认或请求类型的函数 - 它必须使用的是用于存储结果的列表,用于执行转换的函数,和数据(可能是一个单项,或两个项目)。
这是一个棘手的问题:默认转换器函数应该正确处理任意数量的输入项,并按原样返回 - 而不是使用一系列if / else块来选择正确的默认转换器...换句话说,一个身份功能。
我现在看起来像两个lambda:
lamba x: x
lambda x, y: (x, y)
我真正想要的是一个单一的功能:
identity(x) --> x
identity(x, y) --> x, y
答案 0 :(得分:0)
不,Python没有身份功能,也不太可能获得身份功能。
一个人会是什么样子?或许,更容易回答应该做的事情:
something = ...
something is identity(something)
换句话说,你应该准确地回到你所放入的东西,理想情况下,你应该能够放入任何东西。
一个诱人但不充分的解决方案:
wrong_id1 = lambda x: x
此版本的问题在于我们只能传递单个项目,因此可以使用:
>>> wrong_id1('a thing')
'a thing'
但这不是:
>>> wrong_id1('a thing', 'and another thing')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <lambda>() takes exactly 1 argument (2 given)
下一个诱人的解决方案可能是:
wrong_id2 = lambda *x: x
这适用于多个输入:
>>> (1, 2, 3) == wrong_id2(1, 2, 3)
True
但单输入效果不佳:
>>> 9 == wrong_id2(9)
False
问题在于,为了接受多个输入,必须使用*args
,但它具有将单项输入转换为元组的副作用,而简单的wrong_id2
只是返回那个元组:
>>> wrong_id2(9)
(9,)
现在我们知道问题是什么,我们可以编写一个正确的身份函数:
def identity(*args):
if len(args) == 1:
# only one item passed in, return that one item
return args[0]
# many items passed in, return them as a tuple
return args
一些简单的测试表明它的工作原理如下:
>>> 'a thing' == identity('a thing')
True
>>> (1, 2, 3) == identity(1, 2, 3)
True
>>> a_tuple = 7, 8, 9
>>> a_dict = {True: 'Python Rocks!', False: 'up is down'}
>>> none = None
>>> (a_tuple, a_dict, none) == identity(a_tuple, a_dict, none)
True
>>> a_tuple is identity(a_tuple)
True
>>> a_dict is identity(a_dict)
True
>>> none is identity(none)
True
DaoWen对identity
的实现提出了一些有趣的观点,主要的一点是返回值的一致性 - 也就是说,即使单个项目案例返回一个元组,那么我们也可以一直对待它:在其上调用len()
,将其放入for
循环等等。
虽然这可能是非常方便的行为,但这不是身份功能,原因很简单1 != (1, )
- 因此identity(1)
应该返回1
而不是(1, )
}。