【问题标题】:How to use the value of a non-default argument as the default value for a default argument in Python?如何使用非默认参数的值作为 Python 中默认参数的默认值?
【发布时间】:2012-08-01 12:38:32
【问题描述】:

这是我的班级吧:

class Bar:
    def __init__(self, start, end, open, volume, high=open, low=open, last=open):
        self.start = start
        self.end = end
        self.open = open
        self.high = high
        self.low = low
        self.last = last
        self.volume = int(volume)

    def __str__(self):
        return self.start.strftime("%m/%d/%Y\t%H:%M:%S") + "\t" + self.end.strftime("%H:%M:%S") + "\t" +str(self.open) + "\t" + str(self.high) + "\t" + str(self.low) + "\t" + str(self.last) + "\t" + str(self.volume)

1) 我正在尝试初始化最高价、最低价和最后价的任何开盘价。这是正确的做法吗?

2) 当我执行 print(str(bar)) 时,我会得到有趣的输出,例如...

03/13/2012 12:30:00 13:30:00 138.91 <built-in function open> 138.7 <built-in function open> 13177656

【问题讨论】:

    标签: python default-value default-arguments


    【解决方案1】:

    如果你把你的函数写成

    def __init__(self, start, end, foo, volume, high=foo, low=foo, last=foo):
        self.start = start
        self.end = end
        self.open = foo
        self.high = high
        self.low = low
        self.last = last
        self.volume = int(volume)
    

    您会收到一个 NameError 抱怨名称 foo 未定义。这是因为参数的默认值不能引用另一个参数,当您尝试取其值时,该参数尚未定义。 (默认值是在定义方法时设置的,而不是在调用时设置的。)

    但是,open 是 Python 中的内置函数,所以它定义了;这不是你想要的open。这样做的正确方法可能是

    class Bar:
        def __init__(self, start, end, open, volume, high=None, low=None, last=None):
            self.start = start
            self.end = end
            self.open = open
            self.high = open if high is None else high
            self.low = open if low is None else low
            self.last = open if last is None else last
            self.volume = int(volume)
    

    此外,您可能希望使用 'open_' 而不是 'open' 作为参数名称,以避免混淆(并暂时隐藏)内置函数。

    【讨论】:

    • 我不会使用_open,因为它将变量指定为某种方式“受保护”。我认为当您想避免使用关键字时,使用 open_ 会稍微习惯一些(我会扩展它以避免隐藏内置函数)。否则,好的答案(+1)
    • 在这种情况下,太多可能无关紧要,因为变量会立即分配给实例属性self.open。但是,我认为即使是常规参数也可以使用 argname=value 语法调用,因此在这种情况下会产生(小)差异。
    • open 参数的最大问题是尝试在此方法中实际调用open 函数,尽管__builtin__.open 可用。
    • 是的。您在回答中很好地解决了最大的问题。我只是添加一个(非常)次要的点来帮助它稍微好一点。
    【解决方案2】:

    您知道吗,open 是用于打开文件的内置 Python 函数?也就是说,您将 method 分配给变量。

    【讨论】:

    • 很好地解释了#2!谢谢。为什么它适用于低价值?如果我将open 重命名为其他名称,是否是初始化其他变量的正确方法?
    • @Joshua:不,不是。请参阅我的答案,了解为什么它不起作用。
    【解决方案3】:

    这不起作用。

    默认参数在解析函数时准确计算一次。这意味着它必须有一个值:方法签名中的其他形式参数没有值。它们更像是占位符。因此,不可能做你想做的事。

    Python 将搜索一个名为 open 的预先存在的标识符,当函数执行时,始终将它当时表示的那个对象分配给您的变量 highlow

    【讨论】:

      【解决方案4】:

      我认为你做不到。您有该输出,因为“打开”考虑了内置函数 open()。如果不调用 open 而是使用其他名称,则会出现错误。

      如果 low、high 和 last 不能是 None,你可以这样做:

      class Bar:
      def __init__(self, start, end, open, volume, high=None, low=None, last=None):
          self.start = start
          self.end = end
          self.open = open
          self.high = high if high is not None else open
          self.low = low if low is not None else open
          self.last = last if last is not None else open
          self.volume = int(volume)
      

      【讨论】:

        【解决方案5】:

        在:

        def __init__(self, start, end, open, volume, high=open, low=open, last=open)
        

        open 指的是内置的open 方法。将方法作为参数传递在某些情况下非常有用,例如:max(sequence, key=itemgetter(2)) 需要可调用的地方。

        我怀疑您希望默认 highlowlast 成为传递给 __init__open 的值,在这种情况下我会使用关键字参数。

        def __init__(self, start, end, open, volume, **kwargs):
            for k in ('high', 'low', 'last'):
                setattr(self, k, kwargs.get(k, open))
        

        或者:

        def __init__(self, start, end, open, volume, high=None, low=None, last=None):
            if high is None:
                self.high = open
            # etc...
        

        我也不会使用open 作为名字...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-12-14
          • 1970-01-01
          • 2017-11-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-05-07
          相关资源
          最近更新 更多