Несмотря на то, что @ chepner использует type
- хорошее использование argparse
, подход может быть сложным для правильного понимания и понимания.
Как написано, в методе add_argument
возникает ошибка:
Traceback (most recent call last):
File "stack50799294.py", line 18, in <module>
p.add_argument("-e", "--estimator", type=estimators.get, default=Lasso, choices=estimators.keys())
File "/usr/lib/python3.6/argparse.py", line 1346, in add_argument
type_func = self._registry_get('type', action.type, action.type)
File "/usr/lib/python3.6/argparse.py", line 1288, in _registry_get
return self._registries[registry_name].get(value, default)
TypeError: unhashable type: 'dict'
Проверяется, является ли параметр type
элементом в registry
или допустимой функцией.Я не уверен, почему возникает эта ошибка.
def mytype(astr):
return estimators.get(astr)
лучше работает в type=mytype
.Но есть еще один уровень сложности - choices
- это строка keys()
.Но mytype
возвращает класс, выдающий ошибку вроде:
0942:~/mypy$ python3 stack50799294.py -e GBR
usage: stack50799294.py [-h] [-e {Lasso,GBR}]
stack50799294.py: error: argument -e/--estimator: invalid choice: <class '__main__.GradientBoostingRegressor'> (choose from 'Lasso', 'GBR')
Чтобы избежать этих трудностей, я бы предложил разделить аргумент на отображение класса.Это должно быть проще для понимания и расширения:
import argparse
class Lasso():pass
class GradientBoostingRegressor():pass
# Map an easy-to-type string to each function
estimators = {
'Lasso': Lasso,
'GBR': GradientBoostingRegressor
}
p = argparse.ArgumentParser(description="Perform ML regression.")
p.add_argument("-e", "--estimator", default='Lasso', choices=estimators.keys())
args = p.parse_args()
print(args)
estimator = estimators.get(args.estimator, None)
if estimator is not None:
print(type(estimator()))
образцов:
0946:~/mypy$ python3 stack50799294.py -e GBR
Namespace(estimator='GBR')
<class '__main__.GradientBoostingRegressor'>
0946:~/mypy$ python3 stack50799294.py
Namespace(estimator='Lasso')
<class '__main__.Lasso'>
0946:~/mypy$ python3 stack50799294.py -e Lasso
Namespace(estimator='Lasso')
<class '__main__.Lasso'>
0946:~/mypy$ python3 stack50799294.py -e lasso
usage: stack50799294.py [-h] [-e {Lasso,GBR}]
stack50799294.py: error: argument -e/--estimator: invalid choice: 'lasso' (choose from 'Lasso', 'GBR')
const
параметр
Вы можете использовать store_const
для выбора между 2классы, default
и const
:
parser.add_argument('-e', action='store_const', default=Lasso(), const=GradientBoostingRegressor())
, но это не может быть обобщено на большее.`Nargs = '?'предоставляет 3 варианта выбора - по умолчанию, const и пользовательский.Но все еще существует проблема преобразования строки командной строки в объект класса.
Подпарсеры, https://docs.python.org/3/library/argparse.html#sub-commands, показывает, как set_defaults
может использоваться для установки функций или классов.Но чтобы использовать это, вы должны определить подпарсер для каждого выбора.
В общем, лучше начать с простого подхода argparse
, принимая строки и выбор строк, а затем сопоставляя их.Использование дополнительных функций argparse
может произойти позже.
get
error
@chepner's
error имеет отношение к тому, как Python просматривает метод d.get
.Несмотря на то, что он выглядит как метод, он каким-то образом видит dict
, а не метод:
In [444]: d = {}
In [445]: d.get(d.get)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-445-c6d679ba4e8d> in <module>()
----> 1 d.get(d.get)
TypeError: unhashable type: 'dict'
In [446]: def foo(astr):
...: return d.get(astr)
...:
...:
In [447]: d.get(foo)
Это можно рассматривать как базовую ошибку Python или ошибку argparse, но определяемую пользователем функцию илиЛямбда - это легкая работа.