Как использовать именованные параметры в методах Python, которые по умолчанию соответствуют значению уровня класса?

Сценарий использования:

# case #1 - for classes a = MyClass() # default logger is None a = MyClass(logger="a") # set the default logger to be "a" a.test(logger="b") # this means that logger will be "b" only inside this method a.test(logger=None) # this means that logger will be None but only inside this method a.test() # here logger should defaults to the value specified when object was initialized ("a") 

Как я могу реализовать MyClass , чтобы иметь возможность использовать его, как указано выше?

Предположим, что у меня есть несколько методов внутри MyClass которые могут принимать параметр logger named, поэтому я был бы признателен за решение, которое не требует добавления большого количества дубликатов кода в начале каждого метода test...() .

Я читал о примере дозорного , но это не работает для классов, и я бы не хотел добавлять глобальную переменную, чтобы внутри объекта-дозорника.

     _sentinel = object() class MyClass(object): def __init__(self, logger=None): self.logger = logger def test(self, logger=_sentinel): if logger is _sentinel: logger = self.logger # in case you want to use this inside a function from your module use: _sentinel = object() logger = None def test(logger=_sentinel) if logger is _sentinel: logger = globals().get('logger') 

    две основные идеи: захват набора именованных значений, которые могут быть (или могут отсутствовать) локально переопределены в keywords-parameters dict; используя объект-опознаватель в качестве значения по умолчанию, чтобы однозначно идентифицировать, был ли явно передан определенный именованный аргумент или нет (для этой цели часто используется None ( None ), но когда, как здесь, вы хотите, чтобы None как «значение первого класса» для параметра , уникальный объект-дозорный будет делать то же самое).

     class MyClass(object): def __init__(self, logger=None): self.logger = logger def test(self, **kwargs): logger = kwargs.get("logger", self.logger) # use logger, which is sourced as given in OP 

    Заметки

    • Использование **kwargs необходимо, так как вы разрешаете значения None для переменной logger с именем в MyClass.test . Вы могли бы покончить с этим, если бы выбрали какое-то другое значение дозорного (но None самое распространенное).
    • В первоначальном вопросе неясно, нужен ли вам класс или экземпляр по умолчанию. Тот, который указан выше, является экземпляром по умолчанию, то есть регистратором по умолчанию во всех экземплярах MyClass является None , установленным в конструкторе MyClass .
     class MyClass(object): def __init__(self, logger = None): self.logger = logger def test(self, **kwargs): logger = self.logger if kwargs.has_key("logger"): logger = kwargs.get(logger) print "logger is %s" logger.name 

    Краткое объяснение: test начинается с предположения, что он будет использовать регистратор экземпляра. Однако, если явный регистратор передается как аргумент командной строки, он будет использоваться вместо этого. Если logger = None передается в качестве аргумента ключевого слова, то регистратор не используется.