【问题标题】:Initialize parameter of method with default value使用默认值初始化方法的参数
【发布时间】:2012-10-25 18:37:47
【问题描述】:

如果没有将显式值传递给方法,我想用一些默认值初始化方法的参数 - 像这样:

class Example
   def __init__(self, data = self.default_data()):
      self.data = data

   def default_data():
      # ....
      return something

我得到了错误:

NameError: name 'self' is not defined

我该如何解决这个问题?

【问题讨论】:

标签: python


【解决方案1】:

这里的常见习惯用法是将默认值设置为某个标记值(None 是典型的,尽管some have suggested Ellipsis 用于此目的),然后您可以检查它。

class Example(object): #inherit from object.  It's just a good idea.
   def __init__(self, data = None):
      self.data = self.default_data() if data is None else data

   def default_data(self):  #probably need `self` here, unless this is a @staticmethod ...
      # ....
      return something

您可能还会看到用于标记的 object() 实例。

SENTINEL = object()
class Example(object):
   def __init__(self, data = SENTINEL):
      self.data = self.default_data() if data is SENTINEL else data

后一个版本的好处是您可以将None 传递给您的函数,但也有一些缺点(参见下面@larsmans 的cmets)。如果您不预见需要将 None 作为有意义的参数传递给您的方法,我会提倡使用它。

【讨论】:

  • An object() as sentinel 的缺点是它在文档字符串中显示非常丑陋,并且默认行为更难以通过显式方式获得,因此传递 None 是执行此操作的常用方法(在 stdlib 和我知道的大多数其他 Python 库中)。
  • @larsmans -- 我也更喜欢None,但如果None 恰好是您想要传递的东西,那么object() 是下一个最佳选择。如果你真的想要,你可以继承对象并覆盖__repr__ 以使help 看起来更好......另外,如果你导入Example,你也可以导入SENTINEL。
  • 如果使用 Python 3.x,从object 继承是自动的。
  • @NoctisSkytower -- 我很清楚这一点。但是,我发现尝试编写与 python2.x 和 python3.x 都兼容的代码是有实际价值的——还有一个脚本 2to3,但不是 3to2 ......这是一件容易做的事,并且使代码更便携。从这个角度来看,无论如何继承 object 似乎是有意义的。
  • 在 3.x 中,'...' 编译为 Ellipsis 单例,因此您实际上可以使用 foo(bar=...)。
猜你喜欢
  • 1970-01-01
  • 2015-02-25
  • 2021-11-27
  • 1970-01-01
  • 2017-11-19
  • 2011-08-23
  • 1970-01-01
  • 2017-11-22
  • 1970-01-01
相关资源
最近更新 更多