【问题标题】:super() and @staticmethod interactionsuper() 和@staticmethod 交互
【发布时间】:2015-01-03 11:24:59
【问题描述】:

super() 不应该与静态方法一起使用吗?

当我尝试类似的东西时

class First(object):
  @staticmethod
  def getlist():
    return ['first']

class Second(First):
  @staticmethod
  def getlist():
    l = super(Second).getlist()
    l.append('second')
    return l

a = Second.getlist()
print a

我收到以下错误

Traceback (most recent call last):
  File "asdf.py", line 13, in <module>
    a = Second.getlist()
  File "asdf.py", line 9, in getlist
    l = super(Second).getlist()
AttributeError: 'super' object has no attribute 'getlist'

如果我将静态方法更改为类方法并将类实例传递给 super(),则一切正常。我在这里错误地调用 super(type) 还是我遗漏了什么?

【问题讨论】:

    标签: python python-2.7 static-methods super


    【解决方案1】:

    简短的回答

    我在这里错误地调用 super(type) 还是我遗漏了什么?

    是:是的,你叫错了......并且(确实,因为)你缺少一些东西。

    但不要难过;这是一个极其困难的课题。

    documentation 指出

    如果省略第二个参数,则返回的超级对象是未绑定的。

    unbound super 对象的用例极其狭窄且罕见。有关他在super() 上的讨论,请参阅 Michele Simionato 的这些文章:

    此外,他强烈主张从 Python 3 here 中删除未绑定的 super

    我说你称它“不正确”(尽管没有上下文,正确性在很大程度上是没有意义的,而且一个玩具示例并没有提供太多上下文)。因为未绑定的super 非常罕见,并且可能完全不合理,正如 Simionato 所说,使用 super() 的“正确”方式是提供第二个参数。

    在您的情况下,使您的示例工作的最简单方法是

    class First(object):
      @staticmethod
      def getlist():
        return ['first']
    
    class Second(First):
      @staticmethod
      def getlist():
        l = super(Second, Second).getlist()  # note the 2nd argument
        l.append('second')
        return l
    
    a = Second.getlist()
    print a
    

    如果您认为这样看起来很有趣,那您就没有错。但我认为大多数人在看到super(X) 时所期待的(或者当他们在自己的代码中尝试时所希望的)是 Python 为您提供的 super(X, X)

    【讨论】:

    • 这在 Python 3 中是否有任何不同,其中 super() 不带任何参数是在常规方法中调用它的常用方法?调用super().foo()时,我在Python3中遇到了同样的问题。
    • @gerrit:Python 3 的零参数super() 仅适用于类或实例方法。这是由于它用于确定它被定义在哪个类中的魔法。在静态方法中(就像在常规的模块级函数中一样),您仍然需要两个显式参数。 (单参数形式在 Python 3 中仍然是未绑定的。)
    【解决方案2】:

    由于 Second 继承了 First 形式,您可以只使用 First.getlist() 而不是在 super 中传入两个参数(即 super(Second, Second)

    class First(object):
       @staticmethod
       def getlist():
         return ['first']
    
    class Second(First):
      @staticmethod
      def getlist():
        # l = super(Second, Second).getlist()
        l = First.getlist()
        l.append('second')
        return l
    
    a = Second.getlist()
    print (a)
    

    【讨论】:

    • 但是,如果您稍后更改祖先,这可能会搞砸。例如,如果在FirstSecond 之间的继承树中添加了一个中间类OnePointFive,则Second 在调用它的父级时将跳过一个级别。
    【解决方案3】:

    当您在对象实例上调用普通方法时,该方法接收对象实例作为第一个参数。可以获取tte对象的类及其父类,所以调用super是有意义的。

    当您在对象实例或类上调用classmethod 方法时,该方法接收该类作为第一个参数。它可以获取父类,所以调用super是有意义的。

    但是当您调用staticmethod 方法时,该方法不会收到任何内容,也无法知道它是从哪个对象或类调用的。这就是您无法在staticmethod 中访问super 的原因。

    【讨论】:

      猜你喜欢
      • 2010-12-14
      • 1970-01-01
      • 2013-04-16
      • 2011-05-27
      • 2018-09-29
      • 2018-05-26
      • 2021-10-19
      • 2010-10-30
      • 2013-07-01
      相关资源
      最近更新 更多