在接收到所有参数之前,我们可以使用关键字参数和 curry 吗?
Can we use keyword arguments and curry until all arguments are received?
我们可以使用关键字参数和 curry 函数直到所有参数以任意顺序接收吗?
例如我有这个代码:
def create_folder_transformer(folder):
return lambda predicate: lambda file_transformer: map(file_transformer,
filter(predicate,
os.listdir(folder)))
我可以创建一个带有特定文件夹的 folder_transformer
,然后提及`predicate 等。但它有特定的顺序。但是,我认为它不需要与该顺序相关联。
我想实现这样的目标:
- 如果我通过
predicate
,我会得到一个需要 folder
的部分函数
和 file_transformer
作为参数。现在,如果我提供 folder
,我会得到一个采用 file_transformer
. 的偏函数
- 如果我传递
file_transformer
,我得到一个以 predicate
和 folder
作为参数的偏函数。现在,如果我提供 predicate
,我会得到一个采用 folder
. 的偏函数
简而言之,是否有一个内置的部分创建器递归地不断生成部分函数,直到获得所有输入;如果满足输入,只需执行代码。我相信它在 Haskell 中被称为 currying 并且它是函数默认执行的方式。
我认为可能有帮助的用例:
当我使用 n
操作转换特定的 folder
时,
使用 folder
创建部分会更好。
当我有一个特定的谓词时 - 过滤掉许多文件夹中的 mp4
文件 - 带有 predicate
的部分如 string.endswith(".mp4")
会更好。
我阅读了部分 docs 但如果我没有填写一些参数,这些部分不会 return 部分。但是既然我已经声明为None
,我也不能指望它。理想情况下,我希望我的 function 本身表现得像那样,甚至不用担心使用像 partial 这样的附加函数,即它应该被烘焙到我的函数中。
def folder_transformer(folder=None, predicate=None, transformer=None):
return map(transformer, filter(predicate, os.listdir(folder)))
file_transformer = partial(folder_transformer, predicate=os.path.isfile)
# This gives me a "map" object, but I want another partial takes "transformer".
current_transformer = file_transformer(folder=folder)
# This works, but my question is can I make my function do this automatically.
current_transformer = partial(file_transformer,folder=folder)
我带了一个小脚本供我个人使用。
PS: 如果有人知道可以做类似事情的库,请告诉我。
import inspect
def curry(function):
original_func = function
original_args = inspect.signature(function).parameters
def wrapper(**kwargs):
call = True
current_args = {}
for each in original_args:
if kwargs.get(each):
current_args[each] = kwargs.get(each)
else:
call = False
if call:
original_func(**current_args)
else:
def partial(**nargs):
current_args.update(nargs)
return wrapper(**current_args)
return partial
return wrapper
@curry
def foo(a=None, b=None, c=None):
print(a, b, c)
# first partial
bar_with_a = bar(a=1)
# next partial
bar_with_a_and_b = bar_with_a(b=1)
# next partial
bar_with_a_and_b = bar_with_a_and_b(b=2)
# next partial
bar_with_a_and_b = bar_with_a_and_b(a=2)
# call
bar_with_a_and_b(c=2)
我们可以使用关键字参数和 curry 函数直到所有参数以任意顺序接收吗?
例如我有这个代码:
def create_folder_transformer(folder):
return lambda predicate: lambda file_transformer: map(file_transformer,
filter(predicate,
os.listdir(folder)))
我可以创建一个带有特定文件夹的 folder_transformer
,然后提及`predicate 等。但它有特定的顺序。但是,我认为它不需要与该顺序相关联。
我想实现这样的目标:
- 如果我通过
predicate
,我会得到一个需要folder
的部分函数 和file_transformer
作为参数。现在,如果我提供folder
,我会得到一个采用file_transformer
. 的偏函数
- 如果我传递
file_transformer
,我得到一个以predicate
和folder
作为参数的偏函数。现在,如果我提供predicate
,我会得到一个采用folder
. 的偏函数
简而言之,是否有一个内置的部分创建器递归地不断生成部分函数,直到获得所有输入;如果满足输入,只需执行代码。我相信它在 Haskell 中被称为 currying 并且它是函数默认执行的方式。
我认为可能有帮助的用例:
当我使用
n
操作转换特定的folder
时, 使用folder
创建部分会更好。当我有一个特定的谓词时 - 过滤掉许多文件夹中的
mp4
文件 - 带有predicate
的部分如string.endswith(".mp4")
会更好。
我阅读了部分 docs 但如果我没有填写一些参数,这些部分不会 return 部分。但是既然我已经声明为None
,我也不能指望它。理想情况下,我希望我的 function 本身表现得像那样,甚至不用担心使用像 partial 这样的附加函数,即它应该被烘焙到我的函数中。
def folder_transformer(folder=None, predicate=None, transformer=None):
return map(transformer, filter(predicate, os.listdir(folder)))
file_transformer = partial(folder_transformer, predicate=os.path.isfile)
# This gives me a "map" object, but I want another partial takes "transformer".
current_transformer = file_transformer(folder=folder)
# This works, but my question is can I make my function do this automatically.
current_transformer = partial(file_transformer,folder=folder)
我带了一个小脚本供我个人使用。
PS: 如果有人知道可以做类似事情的库,请告诉我。
import inspect
def curry(function):
original_func = function
original_args = inspect.signature(function).parameters
def wrapper(**kwargs):
call = True
current_args = {}
for each in original_args:
if kwargs.get(each):
current_args[each] = kwargs.get(each)
else:
call = False
if call:
original_func(**current_args)
else:
def partial(**nargs):
current_args.update(nargs)
return wrapper(**current_args)
return partial
return wrapper
@curry
def foo(a=None, b=None, c=None):
print(a, b, c)
# first partial
bar_with_a = bar(a=1)
# next partial
bar_with_a_and_b = bar_with_a(b=1)
# next partial
bar_with_a_and_b = bar_with_a_and_b(b=2)
# next partial
bar_with_a_and_b = bar_with_a_and_b(a=2)
# call
bar_with_a_and_b(c=2)