如何使用 functools.partial 和 os.path.join?

How to use functools.partial with os.path.join?

有一个路径 + 文件名的列表,都以相同的 root_dir 开头。如何使用部分?

尝试

from os.path import join as path_join
from functools import partial
from tempfile import gettempdir

root_dir = gettempdir()
root_join = partial(path_join, path=root_dir)
root_join('foo')

但是这会引发错误:

TypeError: join() got multiple values for keyword argument 'path'


显然我可以写一个新函数:

root_join = lambda root=root_dir, *a: path_join(root_dir, *a)

不过我想用 partial 来解决这个问题。有什么线索吗?

只需删除关键字参数即可:

root_join = partial(path_join, root_dir)

示例输出:

>>> print root_join('foo')
/tmp/foo

解释

partial() 接受要传递给包装函数的关键字参数和位置参数,这些参数与调用结果部分函数时传递的参数相结合,因此:

partial_func = partial(func, positional_1, positional_2, keyword_1='A', keyword_2='B')
partial_func(positional_3, keywork_2='B')

相当于:

func(positional_1, positional_2, positional_3, keyword_1='A', keyword_2='B')

请注意,位置参数按顺序组合,首先是部分参数,然后是调用时提供的参数。与往常一样,它们也出现在关键字参数之前。

这意味着您的代码:

root_join = partial(path_join, path=root_dir)
root_join('foo')

相当于:

path_join('foo', path=root_dir)

这里,'foo' 作为 os.path.join(path, *p)path 参数按位置给出,然后尝试将 path 指定为关键字参数。

根据os.path.join()的定义,os.path.join()的第一个参数名称是path。因此,通过 functools.partial 提供 path 参数作为命名关键字参数会生成在同一键上传递多个值的尝试。

因为functools.partial()也支持提供位置参数,你可以试试这个:

>>> import functools
>>> import os.path
>>> root_join = functools.partial(os.path.join, 'root')
>>> root_join('path/to/somewhere')
'root/path/to/somewhere'