Как использовать functools.partial с 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 () получил несколько значений для ключевого аргумента path


Очевидно, я могу написать новую функцию:

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

Однако я хотел бы решить эту проблему с помощью partial, Любая подсказка, как?

2 ответа

Решение

Просто отбросьте аргумент ключевого слова, и он будет работать:

root_join = partial(path_join, root_dir)

Образец вывода:

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

Explaination

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" задается как path аргумент os.path.join(path, *p) позиционно, а затем есть попытка назначить path в качестве ключевого аргумента, а также.

В соответствии с os.path.join() определение, имя первого аргумента для os.path.join() является path, Так что поставка path Параметр как аргумент именованного ключевого слова через functools.partial генерирует попытку передачи нескольких значений по одному и тому же ключу.

поскольку functools.partial() также поддерживает предоставление позиционного аргумента, вы можете попробовать это:

>>> import functools
>>> import os.path
>>> root_join = functools.partial(os.path.join, 'root')
>>> root_join('path/to/somewhere')
'root/path/to/somewhere'
Другие вопросы по тегам