Korzystając z poniższych, jestem w stanie pomyślnie utworzyć parser i dodać moje argumenty do self._parser
za pomocą metody __init()__
.
class Parser:
_parser_params = {
'description': 'Generate a version number from the version configuration file.',
'allow_abbrev': False
}
_parser = argparse.ArgumentParser(**_parser_params)
Teraz chcę podzielić argumenty na grupy, więc zaktualizowałem swój moduł, dodając kilka klas reprezentujących grupy argumentów (w rzeczywistości istnieje kilka podklas klasy ArgumentGroup
) i aktualizując klasę Parser
.
class ArgumentGroup:
_title = None
_description = None
def __init__(self, parser) -> ArgumentParser:
parser.add_argument_group(*self._get_args())
def _get_args(self) -> list:
return [self._title, self._description]
class ArgumentGroup_BranchType(ArgumentGroup):
_title = 'branch type arguments'
class Parser:
_parser_params = {
'description': 'Generate a version number from the version configuration file.',
'allow_abbrev': False
}
_parser = argparse.ArgumentParser(**_parser_params)
_argument_groups = [cls(_parser) for cls in ArgumentGroup.__subclasses__()]
Jednak teraz widzę błąd.
Traceback (most recent call last):
...
File "version2/args.py", line 62, in <listcomp>
_argument_groups = [cls(_parser) for cls in ArgumentGroup.__subclasses__()]
NameError: name '_parser' is not defined
Czego nie rozumiem, to dlaczego _parser_params
istnieją, gdy są odwoływane przez inny atrybut klasy, ale _parser
pozornie nie istnieje w tym samym scenariuszu? Jak mogę zrefaktoryzować mój kod, aby dodać wymagane grupy parserów?
1 odpowiedź
Wynika to z połączenia dwóch dziwactw Pythona:
- Instrukcje
class
nie tworzą nowego zakresu lokalnego - Listy składane do tworzą nowy zakres lokalny.
W rezultacie nazwa _parser
znajduje się w lokalnym zasięgu, którego najbliższym zasięgiem jest zasięg globalny, więc nie może odnosić się do atrybutu klasy, która ma być.
Prostym obejściem byłoby zastąpienie rozumienia listy zwykłą pętlą for
.
_argument_groups = []
for cls in ArgumentGroup.__subclasses()__:
_argument_groups.append(cls(_parser))
(Lepszym rozwiązaniem byłoby prawdopodobnie zaprzestanie używania atrybutów klas, gdy atrybuty instancji mają większy sens).
Podobne pytania
Nowe pytania
python
Python to wielozadaniowy, wielozadaniowy język programowania dynamicznie typowany. Został zaprojektowany tak, aby był szybki do nauczenia się, zrozumienia i użycia oraz wymuszania czystej i jednolitej składni. Należy pamiętać, że Python 2 oficjalnie nie jest obsługiwany od 01-01-2020. Mimo to, w przypadku pytań Pythona specyficznych dla wersji, dodaj znacznik [python-2.7] lub [python-3.x]. Korzystając z wariantu Pythona (np. Jython, PyPy) lub biblioteki (np. Pandas i NumPy), należy umieścić go w tagach.