代码改变世界

Python 面向对象(一)

2018-06-07 08:18  钱先生  阅读(184)  评论(0编辑  收藏  举报

面向过程编程 (Procedural Programming)

Prodcedural programming uses a list of instructions to tell the computer what to do setp-by-step.

 

面向过程编程依赖 --> procedures

  • 一个procedure 包含一组要被进行计算的步骤, 面向过程又被称为top-down languages, 就是程序从上到下一步步执行, 一步步从上到下, 从头到尾的解决问题.
  • 基本设计思路: 
    • 程序一开始是要着手解决一个大问题, 然后把一个大问题分解成很多小问题或子过程.
    • 这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤解围内解决.
  • 典型的面向过程例子, 数据库编程分三步:
    • 连接数据库
    • 备份数据库
    • 测试备份文件可用性
  • 弊端
    • 如果要对程序进行修改, 对修改的那部分有依赖的各个部分都要修改.
    • 随着程序越来越大, 维护难度也越高
    • 所以一般认为, 如果只是写一些简单的脚本, 做一些一次性任务, 用面向过程的方式是可以的; 但如果要处理复杂的, 且需要不断迭代和维护的, 需要用到面向对象.

 

 

面向对象编程 (Object Oriented Programming)

  • OOP编程是复用"类"和"对象"来创建各种模型来实现对真实世界的描述,
  • 面向对象编程优点:
    • 一方面是因为它可以使程序 的维护和扩展变得更简单, 并且可以大大提高 程序开发效率.
    • 另外, 基于面向对象的程序可以使它人更加容易理解你的代码逻辑, 从而使团队开发变得更从容.
  • 面向对象编程核心特性:
    • Class类
      • 一个类即是对一类拥有相同属性的对象的抽象, 蓝图, 原型. 在类中定义了这些对象都具备的属性(variables(data)) / 共同的方法.
    • Object 对象
      • 一个对象即是一个类的实例化后实例, 一个类必须经过实例化后方可在程序中调用, 一个类可以实例化多个对象, 每个对象亦可以有不同的属性, 就像人类是指所有人, 每个人是具体的对象, 人与人之间有共性, 亦有不同.
    • Encapsulation 封装
      • 在类中对数据的赋值, 内部调用对外部用户是透明的, 这使类变成了一个胶囊或窗口, 里面包含着数据或方法.
      • 作用:
        • 防止数据被随意修改
        • 使外部程序不需要关注对象内部的构造 , 只需要通过此对象对外提供的接口进行直接访问即可.
    • Inheritance 继承
      • 一个类可以派生出子类, 在这个父类里定义的属性, 方法自动被子类继承.
      • 作用:
        • 通过父类 -> 子类的方式以最小代码量的方式实现,不同角色的共同点和不同点 
    • Polymorpism多态
      • 多态是面向对象的重要特性, 简单点说: "一个接口, 多种实现", 指一个基类(父类)中派生出了不同的子类, 且每个子类在继承了同样的方法名的同时以对父类的方法做了不同的实现, 这就是同一种事物表现出的多种形态.
      • 编程其实就是一个将具体世界进行抽象化的过程, 多态就是抽象化的一种体现, 把一系列具体事物 的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话.
      • 对不同类的对象发出相同的消息将会有不同的行为.
        • 比如 , 老板让所有员工在9点钟开始工作, 他只要在9点钟的时候说: "开始工作"即可, 而不需要对销售人员说:"开始销售开作", 对技术人员说:"开始技术工作", 因为"员工"是一个抽象的事物, 只要是员工就可以开始工作, 他知道这一点就行了. 至于每个员工, 当然会各斯其职.
      • 多态允许将子类的对象当作父类的对象使用, 某父类型的引用指向其子类型的对象, 调用的方法是该子类型的方法. 这里引用和调用方法的代码编译前就已经决定了, 而引用所指向的对象可以在运行期间动态绑定.

 

无论用什么形式来编程, 要明确以下原则:

  • 写重复代码是非常不好的低级行为
  • 写的代码需要经常变更

 

写代码要遵循的原则

  • 易读 (可读性好)
  • 易改(易扩展)
  • 善用函数
    • 对于需要重复调用的功能, 只需要把它写成一个函数, 然后在程序的各个地方直接调用这个函数名,
    • 当需要修改这个功能时, 只需要修改函数代码.
#!/usr/bin/python
# -*- coding: utf-8 -*-


def dog(name, dog_type):
    data = {
        'name': name,
        'type': dog_type,
        'animal_type': 'dog',
    }
    return data


def bark(d):
    print("dog %s: wang.wang.wang...." % d['name'])


def person(name, age, sex, job):
    data = {
        'name': name,
        'age': age,
        'sex': sex,
        'job': job
    }
    return data


def walk(p):
    print("person %s: walking...." % p['name'])


# 实现上述方法
d1 = dog("李三", "京巴")
p1 = person("李四", 27, "F", "运维")

print((d1['name']))

"""
上述方法可以实现人和狗的不同功能. 
问题: 当把人作为参数传给dob()时, 也不会报错, 还会照常执行.
解决办法: 1. 可以在bard()方法里通过做类型判断, 来区分是不是狗, 是才往下执行, 否则返回错误信息. 
         2. 优化代码
"""

# 代码改进: 把bard方法放进dog()方法中, 并把bark()也作为结果返回


def dog(name, dog_type):
    def bark(d):
        print("dog %s: wang.wang.wang...." % d['name'])

    data = {
        'name': name,
        'type': dog_type,
        'animal_type': 'dog',
        'bark': bark
    }
    return data

def person(name, age, sex, job):
    def walk(p):
        print("person %s: walking...." % p['name'])

    data = {
        'name': name,
        'age': age,
        'sex': sex,
        'job': job,
        'walk': walk
    }
    return data


d1 = dog("李三", "京巴")
print((d1['bark'](d1)))  # 此时把人传进去就不会执行bar().


"""
现实中还有一些不同角色既有共性, 又有区别. 通过面向对象来解决复杂的关系描述:
1. 共性抽出来写一个类
2. 个性抽出来作为子类中特有的变量或方法 
"""
人狗大战