【问题标题】:Declaring Subclass without passing self在不传递 self 的情况下声明子类
【发布时间】:2018-10-30 10:31:19
【问题描述】:

我有一个抽象基类Bicycle

from abc import ABC, abstractmethod

class Bicycle(ABC):

    def __init__(self, cadence = 10, gear = 10, speed = 10):
        self._cadence = cadence
        self._gear = gear         
        self._speed = speed

    @abstractmethod
    def ride(self):
        pass

    def __str__(self):
        return  "Cadence: {0}  Gear: {1}  Speed: {2}".format(self._cadence, 
                                                             self._gear, self._speed)

和一个子类MountainBike

from Bicycle import Bicycle

class MountainBike(Bicycle):

    def __init__(self):
        super().__init__(self)


    def ride(self):
        return "Riding my Bike"

以下代码将导致recursion error,但如果我从super().__init__(self) 中删除self,则对__str__(self): 的调用有效。

问题:

  1. 我在实现__str__(self):时才发现这个错误

    在 Python 3.x 中,从不带参数的子级调用父构造函数时,是否需要传递 self

  2. 假设MountainBike 现在设置了cadencegearspeed,这意味着在我的子类中,构造函数将如下所示:

    class MountainBike(Bicycle):
    
        def __init__(self, cadence, gear, speed):
            super().__init__(cadence,gear,speed)
    

注意,self 没有在 super 中传递,因为据我所知,它可以使变量赋值失效。这个假设正确吗?

【问题讨论】:

  • 在 python 3 中,self 是不需要的,因为我相信 super 可以为您做到这一点,所以:super().__init__() 就足够了(根据您的情况加上 cadence,gear,speed)。
  • 所以,无论有无参数,都不需要传递self,对吗?
  • 没错。
  • 根据官方文档,它被列为强制。 docs.python.org/3/reference/datamodel.html#object.__init__
  • 对。它在第一个 __init__ 中是强制性的,但应该在 super().__init__() 中省略,因为它已经隐式传递到那里。

标签: python python-3.x


【解决方案1】:

self 被隐式传递给 super 调用,因此显式添加它会发送两次:

def __init__(self):
    super().__init__(self)

最终调用Bicycle(self, self),与Bicycle(self, cadence=self) 相同。

稍后,您可能已经尝试将您的实例转换为str(例如打印它),所以这被称为:

def __str__(self):
    return  "Cadence: {0}  Gear: {1}  Speed: {2}".format(self._cadence, 
                                                         self._gear, self._speed)

该代码试图将self._cadence 转换为字符串,而self._cadenceself,因为之前的错误,所以它继续无限递归(直到递归异常)。


请注意,super() 有两种形式:带参数和不带参数,因此有两种正确的方法来修复代码。

Python 3 方式(不带参数):

def __init__(self):
    super().__init__()

旧的 Python 2 方式,更明确:

def __init__(self):
    super(MountainBike, self).__init__()

两者的作用相同,即它们为您提供绑定的 __init__ 方法,该方法已经具有隐式 self

参见此处:https://docs.python.org/3/library/functions.html#super

【讨论】:

  • 因此,无论有无参数,都不需要传递self,对吗?
  • @Sveta 没错。不要通过self
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-20
  • 1970-01-01
  • 2012-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多