python学习笔记day6(递归、二分法,面向对象初始)

一.递归函数(人能理解函数,神能理解递归)

 什么是递归?递归就是自己调用自己本身,一般循环100多次不能解决的问题,就放弃使用递归,下面给出简单示例一看便知:

 

 类似这样函数在不断调用自己本身,就是递归,但大家也会发现,当执行到一定次数之后,函数就会报错退出,这是因为python内部有一个机制

 当达到一定次数之后,程序就会自动退出,下面我们简单测试下:

 

 从这里可以看出,当调用达到998次之后,程序就自动报错退出,但是真正开发,如果调用100多次还没解决问题,就要放弃使用递归,否则影响效率。

 案例一:看这样一个需求:

 # 郭靖比黄蓉大三岁                 4

 # 黄蓉比欧阳锋大三岁             3

 # 欧阳锋比黄老邪大三岁         2

    # 黄老邪今年23岁                   1

    ***  用递归实现郭靖今年多少岁??

   定义几个参数,假设分别为1,2,3,4,然后用递归写一个函数来实现这个需求:

 

 上述函数就简单实现了递归,从上面可以看出,这里先分为四层,也就是age(4)里面传递的4,然后进入函数,执行else条件,此时函   数返回age(3)+3,接下来执行age(3)函数,这时返回age(2)+3+3,然后执行age(2)函数,这时返回age(1)+3+3+3,此时执行age(1)函数,执行if条件语句,返回23+3+3+3 = 32,结果就是32.另外说一下,递归函数都是带有返回值,必须有return

 

 案例二:实现这一一个需求,1 1 2 3 5 8 13 21 。。。。也就是说后一个数是前两个数的和,然后利用递归函数求第十个数是?

 分析:这个需求的规律就是前两个数之和是后一个数  fun(n) = fun(n-1) = fun(n-1),接下来我们试着用函数实现它:

   

   如上就简单实现了这个需求,这里我们拿fun(5)为例简单分析,当调用fun(5)函数时:

   

二.二分法查找

 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。
此方法适用于不经常变动而查找频繁的有序列表。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。接下来给出示例说明下:

 

 案例一:利用递归函数,通过二分查找方法去寻找目标值的索引

 

 三.面向对象编程(上帝的思维)

 1.面向对象编程介绍:

  请用程序描述如下事情:

  • A同学报道登记信息
  • B同学报道登记信息
  • C同学报道登记信息
  • A同学做自我介绍
  • B同学做自我介绍
  • C同学做自我介绍

   

  考虑现实生活中,我们的思维方式是放在学生这个个人上,是学生做了自我介绍。而不是像我们刚刚写出的代码,先有了介绍的行为,再去看介绍了谁。

  用我们的现实思维方式该怎么用程序表达呢?

  

  • 面向过程:根据业务逻辑从上到下写代码
  • 面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程

  面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程的思路是将数据与函数按照执行的逻辑顺序组织在一起,数据与函数分开考虑。

  今天我们来学习一种新的编程方式:面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)

  • 1)解决菜鸟买电脑的故事

    第一种方式:

    1)在网上查找资料

    2)根据自己预算和需求定电脑的型号 MacBook 15 顶配 1W8

    3)去市场找到苹果店各种店无法甄别真假 随便找了一家

    4)找到业务员,业务员推荐了另外一款 配置更高价格便宜,也是苹果系统的 1W

    5)砍价30分钟 付款9999

    6)成交

    回去之后发现各种问题

    第二种方式 :

    1)找一个靠谱的电脑高手

    2)给钱交易

  • 面向对象和面向过程都是解决问题的一种思路而已

    • 买电脑的第一种方式:

      • 强调的是步骤、过程、每一步都是自己亲自去实现的
      • 这种解决问题的思路我们就叫做面向过程
    • 买电脑的第二种方式:

      • 强调的是电脑高手, 电脑高手是处理这件事的主角,对我们而言,我们并不必亲自实现整个步骤只需要调用电脑高手就可以解决问题
      • 这种解决问题的思路就 是面向对象
    • 用面向对象的思维解决问题的重点

      • 当遇到一个需求的时候不用自己去实现,如果自己一步步实现那就是面向过程
      • 应该找一个专门做这个事的人来做
      • 面向对象是基于面向过程的

  需要了解的定义性文字:

  面向对象(object-oriented ;简称: OO) 至今还没有统一的概念 我这里把它定义为: 按人们 认识客观世界的系统思维方式,采用基于对象(实体) 的概念建立模型,模拟客观世界分析、设 计、实现软件的办法。

  面向对象编程(Object Oriented Programming-OOP) 是一种解决软件复用的设计和编程方法。 这种方法把软件系统中相近相似的操作逻辑和操作 应用数据、状态,以类的型式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用。

  2.类和对象

  面向对象编程的2个非常重要的概念:类和对象

  对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类

  类就相当于制作飞机时的图纸,用他来进行创建的飞机就相当于对象

  类:人以类聚 物以群分。 具有相似内部状态和运动规律的实体的集合(或统称为抽象)。 具有相同属性和行为事物的统称

  类是抽象的,在使用的时候通常会找到这个类的一个具体的存在,使用这个具体的存在。一个类可以找到多个对象

  对象:某一个具体事物的存在 ,在现实世界中可以是看得见摸得着的。 可以是直接使用的

  类和对象之间的关系:

  

  小练习:区分类和对象:

    奔驰汽车 类 奔驰smart 类

   张三的那辆奔驰smart 对象

   狗 类 大黄狗 类

   李四家那只大黄狗 对象

   水果 类 苹果 类 红苹果 类 红富士苹果 类

   我嘴里吃了一半的苹果 对象

 3.类的构成

  类有三部分构成:

  类的名称:类名

  类的属性:一组数据

  类的方法:允许对类进行操作的方法,也就是行为

  <1> 举例:

  1)人类设计,只关心3样东西:

  • 事物名称(类名):人(Person)
  • 属性:身高(height)、年龄(age)
  • 方法(行为/功能):跑(run)、打架(fight)

  2)狗类的设计

  • 类名:狗(Dog)
  • 属性:品种 、毛色、性别、名字、 腿儿的数量
  • 方法(行为/功能):叫 、跑、咬人、吃、摇尾巴

   

 4.类的抽象

  如何把日常生活中的事物抽象成程序中的类?

  拥有相同或者类似的属性和行为的对象都可以抽象成一个类

  方法:一般名词都是类(名词提炼法)

  <1> 坦克发射3颗炮弹轰掉了2架飞机

  • 坦克--》可以抽象成 类
  • 炮弹--》可以抽象成类
  • 飞机-》可以抽象成类

  <2> 小明在公车上牵着一条叼着热狗的狗

  • 小明--》 人类
  • 公车--》 交通工具类
  • 热狗--》 食物类
  • 狗--》 狗类

  <3>【想一想】如下图中,有哪些类呢?

  

  说明:人、枪、子弹、手榴弹、刀子、箱子

  <4>【想一想】如下图中,有哪些类呢?

  

  说明:

  • 向日葵
    • 类名: xrk
    • 属性:
    • 行为: 放阳光
  • 豌豆
    • 类名: wd
    • 属性: 颜色 、发型,血量
    • 行为:发炮, 摇头
  • 坚果:
    • 类名:jg
    • 属性:血量 类型
    • 行为:阻挡;
  • 僵尸:
    • 类名:js
    • 属性:颜色、血量、 类型、速度
    • 行为:走 跑跳 吃 死

 5.定义类:

  

  这里的class就是定义类的关键字,用来定义一个类,Person是我们自定义的类的名称,animal和soup是我们定义在类里面的静态变量,work是我们定义的动态方法。

  接下来再看这样一段代码:

  

  可以看出这段程序比上述程序多了一个__init__方法,这里要记住python中凡是带有双下划线的方法都统称为魔法方法,它们都有特殊作用,这里的__init__方法就是py中的构造方法,他的作用就是在实例化对象的时候,就传递相应的参数然后调用这个方法。

  类如何调用查看静态变量动态变量方法:

  1.类名.__dict__方法  只能查看,不能增删改。

  

  2.类名.变量名  可增删改查

  

   3.一般你想查询全部的静态变量时,用__dict__ 其他全部都用类名.变量名

  类操作方法有两种方式:

   (1).类名.__dict__["方法名"]

    

  (2).通过类名.方法名来调用

    

  如果类名操作方法:类名.方法名()

  只要创建一个类,里面的内容就已经自动加载到内存中了

  4.对象

  实例化一个对象:类名()

  例如: p1 = Person()

      p2 = Person()

  p1 对象,实例化对象,类名()过程就叫做实例化。

`    只要实例化对象,就自动触发__init__方法,内部有三部:

  (1).实例化一个对象,在内存中产生一个对象空间

  (2).自动执行__init__方法,并将这个对象空间传给self

  (3).通过构造方法里面的代码给空间对象添加一些属性方法,并返回给对象

  

  5.对象如何查看调用静态变量,动态变量

  对象操作属性变量有两种方法:

  (1).对象.__dict (只能查看)

    

  (2).对象.变量名 (可以增删改查)

    

  (3).可以访问类的静态变量:

    

  一般你想查询全部的静态变量时,用__dict__ 其他全部都用类名.变量名。

  对象操作方法有两种方式:

  (1).对象.方法名()

  

  (2).类名.方法名(对象)

  

  6.小知识:上述的self约定俗成就叫self,也可以改,但最好不要更改

  通过实例化对象查找属性,先从对象空间找,没有则通过类对象指针从 类空间找。

  练习一:在终端输出如下信息:

  小明,10岁,男,上山去砍柴
  小明,10岁,男,开车去东北
  小明,10岁,男,最爱大保健
  老李,90岁,男,上山去砍柴
  老李,90岁,男,开车去东北
  老李,90岁,男,最爱大保健

  

  7.组合

  组合:给一个类对象的属性 封装 另一个类的对象,接下来我们一步步引入:

  (1)创建一个游戏类,分别实例化一个奥特曼和一个怪兽对象,输出奥特曼攻击了怪兽,怪兽还剩多少血量

    

  (2)在上述基础上添加一个武器类,实例化一个激光灯类,输出奥特曼用激光灯攻击了怪兽,怪兽还剩多少血量

   

   上述程序就实现这样的需求,但仔细一想,奥特曼拿激光灯攻击怪兽,主题应该是人,而不像程序中写的那样,主题是激光灯,因此这里就用到了组合,再次改版将上述的主体改为人:

   

  8.面向对象(oop)三大特点,封装、继承、多态。

  (1).什么是继承:

   在现实生活中,继承指的是子女继承父辈的财产:

   

 

   在程序中,继承描述的是事物之间的所属关系,例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物;同理,波斯猫和巴厘猫都继承自猫,而沙皮狗和斑点狗都继承足够,如下所示:

    

  继承可以有效的节省代码,如下示例就是一个简单的继承案例:

  

  如上就是继承,Anima就是父类,也叫基类,而Cat 和 Dog 叫子类,也可以叫派生类。

  python3x 中,所有的类都默认继承object类,继承object类的类称为新式类。
     python中类分为两种:新式类,经典类。但是python3x中只有新式类。
     新式类 :遵循的广度优先。

  经典类 :遵循的深度优先。
  继承又分为:单继承,多继承。

  (2)问题一:看下述代码,猜测哪个方法先执行:

  

  这里是执行顺序的问题,当实例化一个对象调用的时候,会先从自己对象空间也就是子类里面寻找方法,如果找到就停止查找,如果找不到就一直往上查找,直到找到为止。

  问题二:假设子类的属性和方法与父类的一致,如何使用父类的属性和方法呢,这里用到了super关键字:

  

  (3).新式类:遵循的广度优先:

  单继承示例:

  

  多继承:钻石继承

  

  经典类:深度优先
  Python2 中默认是经典类,如果改成新式类 就让 类继承(object)

  多继承:

  

  

 

posted @ 2018-06-13 16:36  淋汐去水  阅读(151)  评论(0)    收藏  举报