Я пытаюсь переопределить функцию, сначала предоставив все позиционные и непозиционные аргументы, а затем предоставив остальную часть аргумента без ключевого слова.
Вот эта функция с предпринятые шаги:
def foo(a, b, c=3, *args, **kwargs):
print(f"Positional: a={a} | b={b} | c={c}")
print("*args", args)
print("**kwargs", kwargs)
from functools import partial
# a partial callable to supply *args later
part = partial(foo, a=2, b=4, c=3, extra=3)
# Here, I expect that the extra arguments would be called
# but instead raises TypeError
part('a', 'b', 'c')
Но вместо этого возникла ошибка.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-bf0b47424a01> in <module>()
11 # Here, I expect that the extra arguments would be called
12 # but instread raises TypeError
---> 13 part('a', 'b', 'c')
TypeError: foo() got multiple values for argument 'a'
Есть ли какое-либо решение этой проблемы, не углубляясь в чтение ее сигнатуры вызываемого (например, используя inspect.signature
et c.)?
РЕДАКТИРОВАТЬ:
Вот реальный код проблемы с Traceback:
import tkinter as tk
from tkinter import ttk
def _builder(parent, label, wtype, *args, **kwargs):
"""
Function to build widgets for configbox.
"""
# creae a container frame with the parent
container = ttk.Frame(parent)
container.pack(fill='x')
# add the elements in the container
# =================================
# pack label
label = ttk.Label(container, text=label)
label.pack(side='left', padx=4, pady=4, fill='x')
# get the widget by name and instantiate
# (fails here)
widget = getattr(ttk, wtype)(container, *args, **kwargs)
# pack and return
widget.pack(side='right', padx=4, pady=4, fill='x')
return widget
class _ConfigBox(tk.Toplevel):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
lframe = ttk.Labelframe(self, text="Configurations")
lframe.pack()
# this does not fail - (no *args or **kwargs)
# place extension entry box
ext_entry = _builder(lframe, "Extension", "Entry")
# THIS PART FAILS!
# bind backend variable with option menu
bkndvar = tk.StringVar(lframe, value="# XXX TEST")
bknd_opts = _builder(
lframe,
"Backend",
"OptionMenu",
# give the *args...
*("TEST1", "TEST2"),
# ...and the **kwargs (fails here)
**dict(variable=bkndvar, default=bkndvar.get()),
)
Traceback:
>>> x = _ConfigBox(tk.Tk())
>>> x.mainloop()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-d0fface65de6> in <module>()
----> 1 x = _ConfigBox(tk.Tk())
2 x.mainloop()
<ipython-input-6-aad9dde31798> in __init__(self, parent, *args, **kwargs)
45
46 # ...and the **kwargs (fails here)
---> 47 **dict(variable=bkndvar, default=bkndvar.get()),
48 )
<ipython-input-6-aad9dde31798> in _builder(parent, label, wtype, *args, **kwargs)
15 # get the widget by name and instantiate
16 # (fails here)
---> 17 widget = getattr(ttk, wtype)(container, *args, **kwargs)
18
19 # pack and return
TypeError: __init__() got multiple values for argument 'variable'