面向对象编程学习笔记(python廖雪峰课程)

https://www.liaoxuefeng.com/wiki/1016959663602400/1017495723838528

这个博客记录一下学习廖雪峰的python课程,整理一下知识点。

1基本概念

面向对象编程OOP(Object oriented Programming)是一种程序设计思想,把对象作为程序的基本单元,一个对象包含了数据操作数据的函数。

面向过程的程序设计是把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。

面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递

假设我们要处理学生的成绩表,这个成绩表有两个属性,一个是学生姓名,一个是对应的成绩,用一个字典表示,

std1 = { 'name': 'Michael', 'score': 98 }
std2 = { 'name': 'Bob', 'score': 81 }

现在我们想打印学生的成绩:

如果采用面向过程的编程,那么我们就调用函数,打印学生成绩即可;

采用面向对象的程序设计思想,我们首先思考的不是程序的执行流程,而是Student这种数据类型应该被视为一个对象,这个对象拥有两个属性,因为需要打印成绩,所以给这个Student类可以关联一个打印成绩的函数(在面向对象编程的时候称之为方法)。给对象发消息实际上是调用对象的关联函数,也就是对象的方法。

面向对象的设计思想是从自然界中来的,因为在自然界中,类(Class)和实例(Instance)的概念是很自然的。Class是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student,比如,Bart Simpson和Lisa Simpson是两个具体的Student。

所以,面向对象的设计思想是抽象出Class,根据Class创建Instance

面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法。

2类/实例/属性/方法

(黑色粗体为固定语法,无须变动;蓝色为需要根据实际需求调整的)

定义最简单的类:

class 类的名称(object):

    pass

根据定义的类创建实例:

实例名称=类的名称()

给实例绑定属性:

可以自由地给实例绑定属性,如下

实例名称.属性名称=属性值/内容

由于类可以起到模板的作用,因此在创建实例的时候,可以把我们认为必须绑定的属性通过__init__这个特殊的方法强制写进去。

定义带属性的类

class 类的名称(object):

    def __init__(self, 属性1名称属性2名称,...):

        self.属性1名称=属性1名称

        self.属性2名称=属性2名称

根据带属性的类创建实例

实例名称=类的名称属性1内容属性2内容,...)

关于__iniit__的注意点

  • __init__的第一个参数永远是self,表示创建的实例本身
  • 有了__init__方法,在创建实例的时候,必须传入与__init__方法相匹配的参数,但self不需要传

定义带属性和方法的类

因为根据带属性的类所创建的实例本身就有属性的内容(数据),要访问这些内容(数据),就没必要从外面的函数去访问,可以直接在类的内部定义访问这些内容(数据)的函数,这样就把内容给封装起来了,这些封装数据的函数和类本身是关联起来的,我们称之为类的方法。

和普通函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是self,并且调用时,不用传递该参数。除此之外,类的方法和普通函数没有什么区别,仍然可以使用默认参数、可变参数、关键字参数和命名关键字参数。

class 类的名称(object):

    def __init__(self, 属性1名称属性2名称,...):

        self.属性1名称=属性1名称

        self.属性2名称=属性2名称

    def 方法1名称(self):

        print(self.属性1名称, self.属性2名称)

    def 方法2名称(self):

        if self.属性1名称>self.属性2名称:

            return 'big'

根据带属性和方法的类创建的实例

实例名称=类的名称属性1内容属性2内容,...)

其形式与根据带属性的类创建实例一样。

这样通过属性把内容(数据)封装,通过方法把逻辑(函数)封装,调用很容易,但却不用知道内部实现的细节

小节

类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据互相独立,互不影响;

方法就是与实例绑定的函数,和普通函数不同的是,方法可以直接访问实例的数据;

通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节;

和静态语言不同,python允许对实例绑定任何数据(实例名称.新属性名称=新属性内容),也就是说,对于同一个类的两个不同实例,拥有的属性可能是不同的。

3继承和多态

在面向对象的程序设计中,最重要的三个特性就是,封装,继承和多态,前面我们已经了解了封装,接下来我们了解一下继承和多态。廖雪峰大神的例子非常好,这里就直接借用了

当我们通过

class 类的名称(object):

...

来定义类的时候,认为这个类是继承自object类(这是所有的类都会继承的类)。

现在假设我们定义了一个动物类,Animal

class Animal(object):
    def run(self):
        print('Animal is running...')

Animal类具有run这个方法。

当我们需要写一个猫类和狗类的时候,因为猫类和狗类也需要跑,所以在猫类和狗类中可以定义一个run方法

class Cat(object):
    def run(self):
        print('Cat is running...')
class Dog(object):
    def run(self):
        print('Dog is running...')

此时,Cat类和Dog类都有run这个方法,一切都没什么问题,猫和狗各自跑各自的,只是麻烦了一点,因为猫类狗类和动物类的跑的方法是一样的。事实上,我们把Animal类可以作为Cat类和Dog类的父类,这样Cat类和Dog类就能继承Animal类的run方法了。(喊一声爸爸就能轻松躺赢)

子类想从父类继承也非常简单,只需要把object换成你想要继承的类的名称就可以了,这样子类就获得了父类的全部功能。当然也可以对子类增加一些新方法。

子类继承父类的功能

class 子类的名称父类的名称):

    def 新方法名称(self):

        ...

子类改写父类的功能

当子类继承了父类的功能,但是想在继承的功能上做修改,这也是可以的

class 子类的名称父类的名称):

    def 父类方法名称(self):

        改写的功能

此时,子类和父类都存在着相同的方法,在运行时,要看具体的实例是根据子类还是父类定义的,如果是根据子类定义的,那么子类的方法会覆盖父类的方法,也就是说会运行改写的功能。这就是多态

小结:

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。

4静态语言和动态语言

对于静态语言(如java)来说,如果一个函数需要传入某个类,则传入的对象必须是这个类或者它的子类;

而对于python这样的动态语言,则不一定需要传入这个类,我们只需要保证传入的类有所需要调用的方法即可。

这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值