Frage Wie benannte Parameter in Python-Methoden verwendet werden, die standardmäßig auf Klassenebene liegen?


Nutzungsszenario:

# 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")

Wie kann ich implementieren? MyClass um es wie oben zu benutzen?

Nehmen wir an, ich habe mehrere Methoden im Inneren MyClass das kann das akzeptieren logger benannte Parameter, so würde ich eine Lösung schätzen, die nicht erfordert, viel Doppelcode zu jedem Anfang hinzuzufügen test...() Methode.

Ich lese über die Sentinel Beispiel, aber das funktioniert nicht für Klassen und ich möchte keine globale Variable hinzufügen, um das Sentinel-Objekt zu behalten.


5
2017-08-25 15:32


Ursprung


Antworten:


_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')

zwei Kernideen: Erfassen der Menge von benannten Werten, die lokal in ein Schlüsselwortparameter-Diktat überschrieben werden können (oder nicht); Verwenden eines Sentinel-Objekts als Standardwert, um eindeutig zu identifizieren, ob ein bestimmtes benanntes Argument explizit übergeben wurde oder nicht (None wird oft für diesen Zweck verwendet, aber wenn, wie hier, Sie wollen None Als ein "First Class Value" für den Parameter wird ein einzigartiges Sentinel-Objekt genauso gut funktionieren.


9
2017-08-25 15:38



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

Anmerkungen

  • Die Verwendung von **kwargs ist notwendig, wie du es erlaubst None Werte für die Logger namens Variable in MyClass.test. Sie könnten damit aufhören, wenn Sie einen anderen Sentinel-Wert gewählt haben (aber None ist am häufigsten).
  • In der ursprünglichen Frage war es unklar, ob Sie einen Klassen- oder Instanzstandard haben wollten. Die oben angegebene ist eine Instanz-Standard, das ist die Standard-Logger über alle MyClass Instanzen ist None, in der MyClass Konstrukteur.

3
2017-08-25 15:38



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

Kurze Erklärung: test beginnt mit der Annahme, dass es den Instanz-Logger verwenden wird. Wenn jedoch ein expliziter Logger als Befehlszeilenargument übergeben wird, wird er stattdessen verwendet. Ob logger = None Wird als Schlüsselwortargument übergeben, dann wird kein Logger verwendet.


1
2017-08-25 15:38