5

使用场景:

# 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命名参数的方法,所以我希望有一个不需要在每个test...()方法的开头添加大量重复代码的解决方案。

我阅读了哨兵示例,但这不适用于类,我不想添加一个全局变量来将哨兵对象保留在里面。

4

3 回答 3

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

两个核心思想:捕获一组可能(或可能不会)被本地覆盖的命名值到关键字参数字典中;使用哨兵对象作为默认值来唯一标识某个命名参数是否已被显式传递(None通常用于此目的,但是当您想要None作为参数的“第一类值”时,a唯一的哨兵对象也可以)。

于 2010-08-25T15:38:59.547 回答
3
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是必要的,因为您允许NoneMyClass.test. 如果您选择了其他一些哨兵值(但None最常见),则可以取消此操作。
  • 如果您想要一个类或实例默认值,原始问题中并不清楚。上面给出的是一个实例默认值,即所有MyClass实例的默认记录器是None,在MyClass构造函数中设置。
于 2010-08-25T15:38:29.767 回答
1
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作为关键字参数传递,则不使用记录器。

于 2010-08-25T15:38:36.537 回答