Необязательные, позиционные и ключевые аргументы Python

Это класс, который у меня есть:

class metadict(dict):
    def __init__(self, do_something=False, *args, **kwargs)
        if do_something:
            pass
        super(metadict,self).__init__(*args,**kwargs)

Идея состоит в том, чтобы инкапсулировать словарь и добавить некоторые функции с помощью специального ключевого слова. Словарь все еще может содержать do_something, хотя вы не можете добавить его во время создания. Во всех остальных аспектах он ведет себя как обычный словарь.

В любом случае, проблема в том, что все, что я даю args, начинается с присвоения первого значения do_something, чего я не хочу.

Что я делаю сейчас, так это:

class metadict(dict):
    def __init__(self, do_something=False, *args, **kwargs)
        if not isinstance(do_something, bool):
            args = list(args)
            args.append(do_something)
        elif do_something:
            pass
        super(metadict,self).__init__(*args,**kwargs)

Но мне это кажется неправильным. Я мог бы также проверить значение do_something в kwargs, но это будет хуже, так как я возился с подписью, удаляя полезную информацию...

Есть ли способ в python безопасно использовать необязательные, позиционные и ключевые аргументы? Если нет, есть ли другие более простые обходные пути?

у меня питон 2.6


person estani    schedule 03.12.2012    source источник
comment
Я считаю, что проблема в том, что вы определяете аргумент ключевого слова перед позиционным аргументом (do_something является ключевым словом, *args является позиционным). Затем, когда вы передаете значение в качестве первого элемента в конструкторе, оно передается в do_something. Попробуйте поставить do_something после *args.   -  person RocketDonkey    schedule 03.12.2012
comment
@RocketDonkey Я пробовал, но, видимо, не поддерживается в python 2.6.   -  person estani    schedule 03.12.2012
comment
А, интересно. Ну в любом случае, вроде разобрались, так что удачи во всем!   -  person RocketDonkey    schedule 03.12.2012
comment
@RocketDonkey нет, но если это есть в версии 3.0, это означает, что простого обходного пути нет. Так что мне просто не повезло.   -  person estani    schedule 04.12.2012
comment
Так что это грязно, может вызвать дополнительные проблемы и определенно не заслуживает ответа (достаточно отказов от ответственности? :) ), но одна вещь, которая работает * для меня, не распаковывает *args (поэтому вместо этого использую args). Затем вы можете поставить do_something=False после args, сделав свою подпись self, args, do_something=False, **kwargs. Затем, когда вы вызываете super, используйте .__init__(args, **kwargs). * Это не работает, если вы используете синтаксис dict(one=1, two=2), поскольку он основан на передаче итерации, которая затем распаковывается самим классом dict. Опять же, ужасное решение, но если вы в отчаянии... :)   -  person RocketDonkey    schedule 04.12.2012


Ответы (1)


Это новое в Python 3. Лучший обходной путь в Python 2 —

def foo(*args, **kwargs):
    do_something = kwargs.pop("do_something", False)

Поведение, которое вы видите, происходит потому, что Python пытается быть умным в сопоставлении аргументов, поэтому, например, он сделает аргумент ключевого слова позиционным, если вы передадите слишком много позиционных аргументов.

PS почему бы не сохранить его как атрибут metadict, а не как запись в словаре?

person Katriel    schedule 03.12.2012
comment
Если ОП беспокоится о подписи, решение простое... задокументируйте функцию. Хорошая документация с разрешенными параметрами, значениями по умолчанию и т. д., что зачастую лучше, чем длинная подпись. - person EnricoGiampieri; 03.12.2012
comment
Атрибут влияет на создание и вообще не сохраняется. По сути, это говорит о том, что словарь, если он присутствует, будет создан с использованием специальной конструкции для предоставления метаданных в словарь, если нет (почти) полностью прозрачен. @EnricoGiampieri Документация великолепна, и я сделаю это, но вам не хватает семантики. Таким образом, inspect не будет работать должным образом, как и инструменты документирования, такие как sphinx. В общем, это просто дизайнерское решение. - person estani; 03.12.2012