我经常会这样处理元组的单个元素:
size, duration, name = some_external_function()
size = int(size)
duration = float(duration)
name = name.strip().lower()
如果some_external_function
返回一些相等类型的元组,我可以使用map
来获得一个(更实用的)封闭表达式:
size, duration, name = map(magic, some_external_function())
是否有类似 element map
的东西?我可以这样运行:
size, duration, name = map2((int, float, strip), some_external_function())
更新:我知道我可以与zip
一起使用理解功能,例如
size, duration, name = [f(v) for f, v in zip(
(int, float, str.strip), some_external_function())]
-我正在寻找“ pythonic”(最佳:内置)解决方案!
致Python开发人员:
那
(size)int, (duration)float, (name)str.strip = some_external_function()
? 如果我在任何即将发布的Python版本中都看到了这一点,我会给您送啤酒:)
答案 0 :(得分:5)
非常简单:使用函数和args unpacking ...
def transform(size, duration, name):
return int(size), float(duration), name.strip().lower()
# if you don't know what the `*` does then follow the link above...
size, name, duration = transform(*some_external_function())
简单,完全可读和可测试的死角。
答案 1 :(得分:3)
地图在这里并不真正适用。当您要对列表的所有元素(例如map(float, list_ints)
)应用简单函数时,它会派上用场。
没有一个明确的内置函数可以执行此操作。但是,一种简化方法并避免n
分别调用要应用的函数的方法可以是定义一个包含函数的可迭代对象,并将其应用于返回的 un-unpacked 从生成器理解函数中获取元组,然后然后解压缩它们:
funcs = int, float, lambda x: x.strip().lower()
t = 1., 2, 'Some String ' # example returned tuple
size, duration, name = (f(i) for f,i in zip(funcs, t))
或者也许更清洁:
def transform(t, funcs):
return (f(i) for f,i in zip(funcs, t))
size, duration, name = transform(t, funcs)
size
# 1
duration
# 2.0
name
# 'some string'
答案 2 :(得分:3)
$ bash 1.sh 1.1
/home/user/tools/EXECUTABLE-1.1/
$ bash 1.sh 1.2
/home/user/tools/EXECUTABLE-1.2/
$ bash 1.sh whatevervalueiput
/home/user/tools/EXECUTABLE-whatevervalueiput/
它远非一纸两用,但它是解决此问题IMO的最具说明性,可读性,可重用性和可维护性的方法。 模型明确显示您的数据,而不是临时处理单个值。
答案 3 :(得分:2)
AFAIK没有内置解决方案,因此我们可以自己编写泛型函数并在以后重用
$brew upgrade subversion
$brew link --overwrite subversion
可能的问题可能是参数的数量可以小于函数的数量,反之亦然,但是在您的情况下,这应该不是问题。 之后
def map2(functions, arguments): # or some other name
return (function(argument) for function, argument in zip(functions, arguments)) # we can also return `tuple` here for example
我们可以更进一步functools.partial
,并为我们的“变形金刚”起个名字,例如
size, duration, name = map2((int, float, str.strip), some_external_function())
并在其他地方重复使用。
答案 4 :(得分:0)
基于Bruno的变换,我认为这是对该问题的最佳答案,我想看看是否可以制作一个通用的变换函数,该函数不需要一组硬编码的格式化程序,但是可以给定任意数量的元素匹配数量的格式化程序。
(除非您需要大量此类魔术贴图器,或者您需要动态生成它们,否则这实在是过大了。)
在这里,我使用的是Python 3.6保证的字典顺序,以其声明的顺序“解压缩”格式化程序,并将其与inputs
可变参数分开。
def transform(*inputs, **tranformer):
return [f(val) for val, f in zip(inputs, tranformer.values())]
size, duration, name = transform(*some_external_function(), f1=int, f2=float, f3=str.lower)
要使流程更加通用并允许预定义的转换功能,可以使用operator.partial
。
from functools import partial
def prep(f_tranformer, *format_funcs):
formatters = {"f%d"%ix : func for ix, func in enumerate(format_funcs)}
return partial(transform, **formatters)
transform2 = prep(transform, int, float, str.lower)
可以用作:
size, duration, name = transform2(*some_external_function())
答案 5 :(得分:0)
我将把布鲁诺的答案列为我的首选。我想这取决于您调用此函数的频率,它将确定重构这种障碍时它具有多少价值。如果您打算多次调用该外部函数,则还可以考虑对其进行修饰:
from functools import wraps
def type_wrangler(func):
def wrangler():
n,s,d = func()
return str(n), int(s), float(d)
return wrangler
def external_func():
return 'a_name', '10', '5.6'
f = type_wrangler(external_func)
print(f())