python中的类与对象2

python中的类与对象2

  • 复习
class Chinese:  # 类的创建
    eye = 'black'  # 类属性的创建

    def __init__(self,hometown):  # 类的初始化方法
        self.hometown = hometown  # 实例属性的创建
        print('程序持续更新中……')  # 初始化中的语句
    
    def born(self):  # 实例方法的创建
        print('我生在%s。'%(self.hometown))  # 方法的具体语句

bazhan = Chinese('广东')  # 类的实例化
print(bazhan.eye)  # 打印实例的属性(从类传递的)
bazhan.born()  # 实例方法的调用

类的继承和定制

继承

  • 我们通过事物的归属关系,使信息的传递更为高效。听到“Python是一种计算机语言”,我们就知道Python可以编程;看到“云浮市在广东省”,我们就明白云浮市在中国南方
  • 我们也可以用一句话,让计算机知道:A类属于B类,自然也拥有了B类的所有属性和方法。这句话在编程里就是:A类继承了B类。
继承
  • 在Python中,我们的习惯表述是:A类是B类的子类,而B类是A类的父类(或超类)。
  • 类的继承,让子类拥有了父类拥有的所有属性和方法。

定制

  • 只有继承的话,子类只是父类的复制而已。我们需要了解另一个重要的概念:类的定制。
  • 子类也可以在继承的基础上进行个性化的定制,包括:(1)创建新属性、新方法;(2)修改继承到的属性或方法。
  • 类的定制,不仅可以让子类拥有新的功能,还能让它有权修改继承到的代码
  • 当我们谈定制时,已经包含了继承。毕竟,类的定制的前提是继承,而定制的加入让类的继承不仅仅只是单纯的复制而已。这也是我们创建子类的意义

类的继承如何写

继承的基础语法

继承的基础语法
  • 子类继承的属性和方法,也会传递给子类创建的实例
# 例
class Chinese:
    eye = 'black'

    def eat(self):
        print('吃饭,选择用筷子。')

class Cantonese(Chinese):  
# 通过继承,Chinese类有的,Cantonese类也有
    pass

# 验证子类可以继承父类的属性和方法,进而传递给子类创建的实例
yewen = Cantonese()  
# 子类创建的实例,从子类那间接得到了父类的所有属性和方法
print(yewen.eye)  
# 子类创建的实例,可调用父类的属性
yewen.eat()  
# 子类创建的实例,可调用父类的方法
  • 通过一个小括号,子类就能轻轻松松地拥有父类所拥有的一切。不用复制大段大段的代码,只要一个括号,就能复用整块代码。

  • 很多类在创建时也不带括号,如class Chinese,实际上,class Chinese:在运行时相当于class Chinese(object):。而object,是所有类的父类,我们将其称为根类(可理解为类的始祖)。
  • 我们可以用一个函数来验证这一点:函数isinstance(),可以用来判断某个实例是否属于某个类。
print(isinstance(1,int))
# 判断1是否为整数类的实例
print(isinstance(1,str))

print(isinstance(1,(int,str)))
# 判断实例是否属于元组里几个类中的一个
# 阅读完代码再运行。
class Chinese:
    pass

class Cantonese(Chinese):
    pass

gonger = Chinese()
# 宫二,电影《一代宗师》女主,生于东北
yewen = Cantonese()
# 叶问,电影《一代宗师》男主,生于广东

print('\n验证1:子类创建的实例同时也属于父类')
print(isinstance(gonger,Chinese))  
print(isinstance(yewen,Chinese))  

print('\n验证2:父类创建的实例不属于子类。')
print(isinstance(gonger,Cantonese))

print('\n验证3:类创建的实例都属于根类。')
print(isinstance(gonger,object))  
print(isinstance(yewen,object))
各级实例与类的关系
  • 在类的继承中,不仅子类属于父类,子类所创建的实例实际上也同时属于父类。
  • 父类可以被无限个子类所继承(这一点好比类的属性方法可以传递给无限个实例)

类的继承之多层继承

# 例
class Earthman:
    eye_number = 2

# 中国人继承了地球人
class Chinese(Earthman):
    eye_color = 'black'

# 广东人继承了中国人,同时也继承了地球人。
class Cantonese(Chinese):
    pass

yewen = Cantonese()
print(yewen.eye_number)
print(yewen.eye_color)
  • 实例yewen可以调用父类Chinese和父类的父类Earthman中的属性。可得结论:子类创建的实例可调用所有层级父类的属性和方法。
  • 多层继承,属于继承的==深度拓展==。而下面要讲的多重继承,则是继承的宽度拓展。

类的继承之多重继承

  • 一个类,可以同时继承多个类,语法为class A(B,C,D):
  • 假设我们将“出生在江苏,定居在广东的人”设为一个类Yuesu,那么,它的创建语句则为class Yuesu(Yue,Su)。
  • class Yuesu(Yue,Su)括号里Yue和Su的顺序是有讲究的。和子类更相关的父类会放在更左侧
  • “出生在江苏,定居在广东的人”在穿着和饮食等方面会更接近广东人,所以将 Yue 放在 Su 的左侧
  • 所以,广东人创建的实例在调用属性和方法时,会先在左侧的父类中找,找不到才会去右侧的父类找。(可理解为“就近原则”)
class Su:
    born_city = 'Jiangsu'
    wearing = 'thick'  # 穿得较厚

    def diet(self):
        print('我们爱吃甜。')

class Yue:
    settle_city = 'Guangdong'
    wearing = 'thin'  # 穿得较薄

    def diet(self):
        print('我们吃得清淡。')

class Yuesu(Yue,Su):
    pass

xiaoming = Yuesu()
print(xiaoming.wearing)
print(xiaoming.born_city)
xiaoming.diet()
# 越靠近子类(即越靠左)的父类,越亲近,越优先考虑。子类调用属性和方法时,会先在靠左的父类里找,找不到才往右找。
多层继承和多重继承
  • 多层继承和多重继承的结合,让继承的类拥有更多的属性和方法,且能更灵活地调用。进而,继承的力量也得以放大了很多倍。

  • 练习
习题
class C0:
    name = 'C0'

class C2(C0):
    num = 2

class C1:
    num = 1

class C3:
    name = 'C3'

class C4(C1,C2,C3):
    pass

ins = C4()
print(ins.name) # 打印出C0
print(ins.num) # 打印出1
  • 可以发现就近原则中的一个细节:多重继承中,若某父类还有父类的话,会先继续往上找到顶。例如代码中的ins.name调用的是C2的父类C0的值而非 C3。

类的定制如何写

定制,可以新增代码

# 例
class Chinese:
    eye = 'black'

    def eat(self):
        print('吃饭,选择用筷子。')

class Cantonese(Chinese):  # 类的继承
    native_place = 'guangdong'  # 类的定制

    def dialect(self):  # 类的定制
        print('我们会讲广东话。')

yewen = Cantonese()
print(yewen.eye)
# 父类的属性能用
print(yewen.native_place)
# 子类的定制属性也能用
yewen.eat()
# 父类的方法能用
yewen.dialect()
# 子类的定制方法也能用
  • 我们可以在子类下新建属性或方法,让子类可以用上父类所没有的属性或方法。这种操作,属于定制中的一种:新增代码。

定制,也可重写代码

  • 例题:已知中国的陆地面积,也知道广东的陆地面积占比为1.88%。
class Chinese:
    def land_area(self,area):
        print('我们居住的地方,陆地面积是%d万平方公里左右。'% area)

class Cantonese(Chinese):
    # 直接对方法进行重写
    def land_area(self,area):
        print('我们居住的地方,陆地面积是%d万平方公里左右。'% int(area * 0.0188))
gonger = Chinese()
yewen = Cantonese()
gonger.land_area(960)
yewen.land_area(960)
        #两个类都有个各自的land_area()方法,但有些冗余
  • 优化代码
class Chinese:

    def land_area(self,area):
        print('我们居住的地方,陆地面积是%d万平方公里左右。'% area)

class Cantonese(Chinese):
    # 间接对方法进行重写
    def land_area(self, area, rate = 0.0188):
        Chinese.land_area(self, area * rate)
        # 直接继承父类方法,再调整参数。

gonger = Chinese()
yewen = Cantonese()
gonger.land_area(960)
yewen.land_area(960)
  • 子类继承父类方法的操作是在def语句后接父类.方法(参数),如上述代码的第八、九行。
  • 父类方法land_area中的说法改变,子类也不用去动,因为子类直接继承了父类的方法。只不过,在继承的基础上,通过参数的调整完成了定制。
  • 参数的调整,可以增加参数(如 rate),也可以改变参数的默认值
class Chinese:

    def land_area(self,area):
        print('我们居住的地方,陆地面积是%d万平方公里左右。' % area)

class Cantonese(Chinese):
    # 为参数 area 设置默认值。
    def land_area(self, area = 960, rate = 0.0188):
        Chinese.land_area(self, area * rate)

yewen = Cantonese()
yewen.land_area()
# 两个参数都有默认值,所以可以这么调用。
  • 例题:通过参数默认值的改变,完成子类的定制,让程序的运行结果为“雷猴!欢迎来到广东。”
class Chinese:

    def __init__(self, greeting = '你好', place = '中国'):
        self.greeting = greeting
        self.place = place

    def greet(self):
        print('%s!欢迎来到%s。' % (self.greeting, self.place))

class Cantonese(Chinese):

    def __init__(self, greeting = '雷猴', place = '广东'):
        Chinese.__init__(self, greeting, place)
    
yewen = Cantonese()
yewen.greet()

练习

练习一

  • 练习要求:每个人都有好几个不同的身份,且不同身份都附带一些特定的特征(属性)和行为(方法)。例如,有这样一群人:在学校时被归在老师,脸是严肃的;亲子关系中(parenthood)则被归到父亲,脸是甜蜜的。
class Teacher:
    face = 'serious'
    job = 'teacher'


class Father:
    face = 'sweet'
    parenthood = 'dad'


class TeacherMore(Teacher, Father):
    pass

class FatherMore(Father, Teacher):
    face = 'gentle'

time3 = TeacherMore()
time4 = FatherMore()
print(time3.face)
print(time4.face)

练习二

  • 练习要求:练习会先提供一个类,用以记录学生学习 Python 的投入时间和有效时间。需要你创建一个子类,为某一类学生提供定制化的记录方案。
class Student:
    def __init__(self, name, job=None, time=0.00, time_effective=0.00): 
        self.name = name
        self.job = job
        self.time = time
        self.time_effective = time_effective

    def count_time(self, hour, rate):
        self.time += hour
        self.time_effective += hour * rate

class Programmer(Student):
    def __init__(self, name):
        Student.__init__(self, name, job='programmer', time=0.00, time_effective=0.00)

    def count_time(self, hour, rate=1):
        Student.count_time(self, hour, rate)

student1 = Student('韩梅梅')
student2 = Programmer('李雷')
print(student1.job)
print(student2.job)
student1.count_time(10, 0.8)
student2.count_time(10)
print(student1.time_effective)
print(student2.time_effective)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353