【问题标题】:Understanding subclasses and __init__ method理解子类和 __init__ 方法
【发布时间】:2018-08-27 09:31:37
【问题描述】:

我有一个问题。我正在学习 Python 并试图理解超类、子类和它们之间的层次结构。我有一件事我不完全理解。 我正在尝试编写一个程序,其中有一个“Person”超类和“Birthday”子类。我为它们定义了 init 方法。我想要做的是,我想创建一个实例的人。同时它应该为生日创建相同的实例。因为所有人都有生日:) 我想使用我在“生日”类中定义的方法。 代码;

import datetime
class Person(object):
    def __init__(self,name):
        self.name=name
        Birthday.__init__(self,name)

    def gender(self,gender):
        self.gender=gender



class Birthday(Person):
    def __init__(self,name):
        self.objectlike=[]
        self.birthday=None
        self.youget={}
    def setbirth(self,year,month,day):
        self.birthday=datetime.date(year,month,day)        
    def getbirth(self):
        return self.birthday
    def __str__(self):
        return self.name
    def setyouget(self,year,thing):
        self.youget[year]=thing
    def setlikeob(self,thing):
        self.objectlike.append(thing)
    def nextbirth(self):
        thisyearbirth=getbirth().year.replace(year=datetime.date.today().year)
        return thisyearbirth
    def howlong(self):
        return self.nextbirth()-datetime.date.today()
    def getage(self):
        age=datetime.date.today().year-self.birthday.year
        return age

问题是当我创建一个 Person 实例时,例如,

joey=Person('Joey Tribiani')

然后我尝试为乔伊设置生日;

joey.setbirth(1980,5,5)

它说:'Person' 对象没有属性 'setbirth'

我该如何克服这个问题?我想我应该在 init 方法中添加一些代码,但我不知道要添加什么。我在 Person 类中添加了“Birthday.init(self,name)”但是没用。

(顺便说一句,这是我的第一个问题。我在这个网站上阅读了很多主题。我对使用它的人的帮助感到惊讶。)

【问题讨论】:

  • 为什么BirthdayPerson 的子类?
  • 继承另一个的类得到了别人的方法,而不是相反。也请阅读this
  • 另外,好的 Python 代码不使用 getter 和 setter。
  • @khelwood 你能给我指出一个资源,上面写着“好的 Python 代码不使用 getter 和 setter”并说明原因吗?
  • 我假设他们在谈论@property,它实际上是一个getter,它实际上有一个setter;所以也许更好的措辞是 python 对 getter 和 setter 有更好的结构。

标签: python class subclass


【解决方案1】:

继承实际上有两个方面 - 子类型(语义)和实现继承(技术)。

从语义上讲,继承描述了一种“是”关系——如果 B 是 A 的子类,那么 B “是”A(有一些特殊化),您应该能够同样使用 A 和 B 的实例方式(这被称为 Liskov 替换原则)。

从技术上讲,继承是一种受限制的组合/委托(从语义上讲,这是一种“具有”关系)- 子类具有对其父类的引用,而方法(和其他类属性)未在子类中定义在父级(和它的父级等)上查找。这意味着继承也可以用于代码重用(“实现继承”),最终不尊重 liskov 替换原则(“类型继承”)

请注意,在 Python 等动态类型语言中,您实际上并不需要 继承来进行子类型化。你可以有一个 B 类实现与 A 类完全相同的接口——根据 Liskov 的说法,这是一个适当的子类型——根本不需要从 A 继承,也没有与 A 的任何共同祖先。

现在回到你的代码......第一个明显的错误是使Birthday成为Person的子类,因为生日显然不是一个人(语义上,关系是一个组合:一个人有一个生日)。第二个明显的错误是认知错误:看起来您以错误的方式获得了继承关系。如果Birthday 继承自Person,那么是Birthday 类可以访问Person 方法,而不是相反。

还有其他明显的问题,但它们并不是真正重要的 ATM。首先从“有一个”(组合/委托)的角度重新考虑您的代码,然后是时候解决这些问题了。

【讨论】:

    【解决方案2】:

    根据上面粘贴的代码Person is the SuperclassBirthday is the Subclass。所以,它是继承自超类的子类,而不是相反。

    另外,Inheritanceis-a 关系。 Have/Has-A 关系对应于composition。你可以阅读更多here

    【讨论】:

      猜你喜欢
      • 2022-09-23
      • 2021-06-19
      • 2017-12-13
      • 2015-12-06
      • 2015-04-19
      • 1970-01-01
      • 2014-09-21
      • 2015-11-27
      • 2011-08-07
      相关资源
      最近更新 更多