Неожиданный аргумент в Python
Использую классовый подход с наследованием и динамическим выбором методов.
Аргументы в методы передаю через словари.
Получаю такую ошибку:
method got an unexpected keyword argument keyword
Пример: def test(a). Я вызываю как: test(a=1, b=2) b - неожиданный аргумент.
Причина как-бы понятна. Понимаю, что можно в методы вписать:
*- Для сбора в кортежи.**- Для сбора в списки.
А игнорировать эти аргументы как-то можно, если нет смысла их собирать. Или лучше позаботится, чтобы в словаре при раскладывании "лишних" аргументов не было?
P.S Суть в том, что методы вызываются динамически, в зависимости от входных параметров, и аргументы прилетают тоже динамически. Мне, чтобы это убрать нужно хранить список всех аргументов методов где-то. Или использовать сбор таких параметров в методах. Есть еще варианты?
Ответы (3 шт):
def strict(a=1):
print(a)
def flexible(**kwargs):
a = kwargs.get('a')
print(a)
args = dict(a=1, b=2)
strict(**args) # Ошибка
flexible(**args) # Нет ошибки, "b" просто проигнорируется
* и ** как операторы-префиксы используются для распаковки итерируемых объектов и словарей, соответственно. И для захвата аргументов переданных в функцию.
Касательно вашего примера
def test(a):
pass
test(a=1, b=2)
Выдаст ошибку, так как функция ожидает только 1 аргумент, а вы передаете неизвестный именованный аргумент, о чем ошибка Вам и сообщает.
Если кол-во входящих параметров неизвестны, то используются выше указанные операторы. как пример:
def test(*args, **kwargs):
for i in args:
print(i)
for k, v in kwargs.items():
print(f'{k}-{v}')
В такую функцию можно передавать сколь угодно параметров.
test(1,2,3, a=4, b=5)
# Out
1
2
3
a-4
b-5
Можно совмещать с ожидаемымси параметрами.
def test(arg1, *args, **kwargs):
print(f'this is arg1 {arg1}')
for i in args:
print(i)
for k, v in kwargs.items():
print(f'{k}-{v}')
#out
this is arg1 1
2
3
a-4
b-5
Так же операторы можно использовать для распаковки аргументов. * - любой итерируемый объект. ** - словарь.
print(*(1, 2, 3)) # 1 2 3
print(*[1, 2, 3]) # 1 2 3
print(*{1, 2, 3}) # 1 2 3
print(*{1: 2, 2: 2, 3: 3}) # 1 2 3
Этим можно пользоваться при передачи параметров в функцию.
dict_args = {
"arg1": 25,
"arg2": 100
}
def test(arg1, arg2):
print(arg2-arg1)
test(**dict_args) # 75
Как вариант, каждому методу кроме нужных ему параметров добавить параметр с двумя звездочками **, тогда все "лишние" именованные параметры будут попадать в этот параметр:
def test(a, **_):
pass
test(a=1, b=2)
args = dict(a=1, b=2)
test(**args) # Так тоже будет работать