Python 3 - 如何 'convert' 一个以字典为参数的函数转换为以关键字参数为参数的函数?
Python 3 - How to 'convert' a function taking a dict as arguments to one which takes keyword arguments?
我有一个函数 g()
以字典作为参数,例如:
>> g({'a':'foo', 'b':'bar', 'c','baz'})
a = foo
b = bar
c = baz
我想 'convert' g()
或从 g()
创建一个新函数 f()
这样它将采用位置参数而不是字典,例如:
>> f(a='foo', b='bar', c='baz')
a = foo
b = bar
c = baz
背景:
- 我的目标是编写一个小的 API,使用户可以轻松利用这个核心包:https://github.com/fmfn/BayesianOptimization。
- 要使用 API,用户必须提供他们的用户定义函数。
- 我的未来API会为核心包提供自定义函数
- 核心包需要采用位置参数(不是字典)的函数。
- 这些用户定义的函数可能很复杂,很可能会接受很多参数,我宁愿告诉用户构建他们的函数时将字典作为参数而不是一长串位置参数(并做某种在调用核心包之前在我的 API 中进行转换)。
或者谁能想到更好的方法来解决这个问题?
谢谢!
本质上,你想要的是一个函数装饰器,它在调用你的函数之前执行某种预处理逻辑。首先,创建你的装饰器。它将接收关键字参数并将其传递给内部函数。
In [239]: def baz(fnc):
...: def inner(**kwargs):
...: fnc(kwargs)
...: return inner
...:
使用 @...
:
用装饰器语法装饰你的原始函数
In [240]: @baz
...: def foo(dict_):
...: for k in dict_:
...: print(k, '=', dict_[k])
...:
调用您的原始函数:
In [241]: foo(a=1, b=2, c=3)
a = 1
b = 2
c = 3
我会使用 exec
方法,因为它允许您做任何您可以在代码中做的事情,所以没有太多额外的东西需要学习。例如,如果将以下代码插入代码中,您可以创建一个简单的函数,该函数对字典中的每个索引都有一个参数,参数标识符是字母表中的每个小写字母(因此只有在您不这样做时才有效) '超过 26 个参数
def MakeFunction(DictionaryToUse):
arguments = ""#Defaults to no arguments
for i in range(97,97+len(DictionaryToUse)):#Adds another argument per dictionary item
arguments += chr(i) + ","
if len(arguments) > 0:
arguments = arguments[:-1]#Removes the last comma, if there is one
exec("def f(" + arguments + """):
print("hi")""",globals())#Defines a new function f so it can be called as a global function.
因此,例如,要创建一个具有 3 个参数的函数,您可以使用:
MakeFunction({"foo":0,"bar":10,"foobar":96})
然后可以调用名为 f
的新函数,带有 3 个参数。
f(1,2,3)
您显然必须根据自己的需要对其进行调整,将 f 替换为您想要的函数名称,并添加您希望函数执行的任何操作,而不是 print("hi")
。
我找到了解决问题的简单方法
这是一个简单的函数 g
以字典作为我想要的参数 'convert':
>>> def g(my_dict):
print('a:', str(my_dict['a']))
print('b:', str(my_dict['b']))
一个接受关键字参数的新函数 f
可以很容易地从 g
:
创建
>>> def f(**kwargs):
return g(kwargs)
让我们尝试 f
使用关键字参数:
>>> f(a='foo', b='bar')
a: foo
b: bar
f
不适用于位置参数:
>>> f('foo', 'bar')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-619-505f263ccdf6> in <module>()
----> 1 f(1, 2)
TypeError: f() takes 0 positional arguments but 2 were given
备注:
- 我最初要求 'converted' 函数
f
接受 位置参数 。在做了更多研究之后,我发现我的意思是 关键字参数 。我在问题中使用了错误的术语,我很抱歉。
- 我对@COLDSPEED 提出的装饰器的尝试只取得了部分成功:我能够创建一个函数
f
,它似乎可以工作,但不知何故,其余代码看到它返回的值是 None
。如果您有任何解释,请随时发表评论。
我有一个函数 g()
以字典作为参数,例如:
>> g({'a':'foo', 'b':'bar', 'c','baz'})
a = foo
b = bar
c = baz
我想 'convert' g()
或从 g()
创建一个新函数 f()
这样它将采用位置参数而不是字典,例如:
>> f(a='foo', b='bar', c='baz')
a = foo
b = bar
c = baz
背景:
- 我的目标是编写一个小的 API,使用户可以轻松利用这个核心包:https://github.com/fmfn/BayesianOptimization。
- 要使用 API,用户必须提供他们的用户定义函数。
- 我的未来API会为核心包提供自定义函数
- 核心包需要采用位置参数(不是字典)的函数。
- 这些用户定义的函数可能很复杂,很可能会接受很多参数,我宁愿告诉用户构建他们的函数时将字典作为参数而不是一长串位置参数(并做某种在调用核心包之前在我的 API 中进行转换)。
或者谁能想到更好的方法来解决这个问题?
谢谢!
本质上,你想要的是一个函数装饰器,它在调用你的函数之前执行某种预处理逻辑。首先,创建你的装饰器。它将接收关键字参数并将其传递给内部函数。
In [239]: def baz(fnc):
...: def inner(**kwargs):
...: fnc(kwargs)
...: return inner
...:
使用 @...
:
In [240]: @baz
...: def foo(dict_):
...: for k in dict_:
...: print(k, '=', dict_[k])
...:
调用您的原始函数:
In [241]: foo(a=1, b=2, c=3)
a = 1
b = 2
c = 3
我会使用 exec
方法,因为它允许您做任何您可以在代码中做的事情,所以没有太多额外的东西需要学习。例如,如果将以下代码插入代码中,您可以创建一个简单的函数,该函数对字典中的每个索引都有一个参数,参数标识符是字母表中的每个小写字母(因此只有在您不这样做时才有效) '超过 26 个参数
def MakeFunction(DictionaryToUse):
arguments = ""#Defaults to no arguments
for i in range(97,97+len(DictionaryToUse)):#Adds another argument per dictionary item
arguments += chr(i) + ","
if len(arguments) > 0:
arguments = arguments[:-1]#Removes the last comma, if there is one
exec("def f(" + arguments + """):
print("hi")""",globals())#Defines a new function f so it can be called as a global function.
因此,例如,要创建一个具有 3 个参数的函数,您可以使用:
MakeFunction({"foo":0,"bar":10,"foobar":96})
然后可以调用名为 f
的新函数,带有 3 个参数。
f(1,2,3)
您显然必须根据自己的需要对其进行调整,将 f 替换为您想要的函数名称,并添加您希望函数执行的任何操作,而不是 print("hi")
。
我找到了解决问题的简单方法
这是一个简单的函数 g
以字典作为我想要的参数 'convert':
>>> def g(my_dict):
print('a:', str(my_dict['a']))
print('b:', str(my_dict['b']))
一个接受关键字参数的新函数 f
可以很容易地从 g
:
>>> def f(**kwargs):
return g(kwargs)
让我们尝试 f
使用关键字参数:
>>> f(a='foo', b='bar')
a: foo
b: bar
f
不适用于位置参数:
>>> f('foo', 'bar')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-619-505f263ccdf6> in <module>()
----> 1 f(1, 2)
TypeError: f() takes 0 positional arguments but 2 were given
备注:
- 我最初要求 'converted' 函数
f
接受 位置参数 。在做了更多研究之后,我发现我的意思是 关键字参数 。我在问题中使用了错误的术语,我很抱歉。 - 我对@COLDSPEED 提出的装饰器的尝试只取得了部分成功:我能够创建一个函数
f
,它似乎可以工作,但不知何故,其余代码看到它返回的值是None
。如果您有任何解释,请随时发表评论。