面向对象(一)

面向对象

  • 与面向过程相比:二狗子准备结婚,需要盖房子

    • 面向过程:数学逻辑的映射,学会做个好员工
    • 面向对象:生活逻辑的映射,学会做个好领导
  • 生活实例

    • 类: 人 手机 电脑
    • 对象: 习大大、小杰 小杰的T2手机、小明的iPhone X 小杰的Mac、小李的华硕
  • 官方定义:

    • 类:具有相同特征(属性和行为)事物的抽象
    • 对象:某个类的具象
  • 编程语言:

    • 类:是一种自定义的数据类型
    • 对象:某个类型的变量

类的语法

  • 定义类:

    1
    2
    class 类名:
    内容
  • 示例:定义一个人的类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    # 定义类
    class Person:
    # 行为的体现,通过方法

    # 吃饭
    def eat(self):
    print('红烧鸡腿我喜欢吃')

    # 打篮球
    def play(self):
    print('俺喜欢打篮球')


    # 声明对象
    bryant = Person()

    # 调用方法
    bryant.eat()
    bryant.play()

    # 设置属性:是动态添加的
    bryant.name = '科比·布莱恩特'
    # 获取属性
    print(bryant.name)
  • 语法:

    • 定义类需要使用关键字:class
    • 类名:原则上只要符合表示标识符的命名规范即可,但我们通常使用大驼峰(每个单词首字母大写)的风格
    • 不要忘记类名后边的冒号
    • 类的内容要进行缩进
    • 行为:通过函数体现,与外面定义函数的方式类似,第一个参数默认是self
    • 属性:通过变量体现,属性是动态添加的,因此在定义时可以不体现
    • 成员访问:
      • 成员属性:对象.属性名
      • 成员方法:对象.方法名()
  • self

    • 示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      class Person:
      def run(self):
      # self表示当前对象:谁调用该方法就代表谁
      print('{}每天以2m/s的速度锻炼5km'.format(self.name))

      def introduce(self):
      # self这个名字可以是任意的,但是通常都是要用这个
      # 既可以访问成员属性
      print('我叫{}'.format(self.name))
      # 也可以访问成员方法
      self.run()


      mugai = Person()
      mugai.name = '木盖'

      # print(mugai)
      mugai.run()

      curry = Person()
      curry.name = '史蒂芬·库里'
      curry.run()

      # 调用方法时第一个参数self不需要传递
      curry.introduce()
    • 说明:

      • 每个成员方法都有这么一个参数,调用的时候不需要传递
      • 名字可以不是self,只不过通常我们都要self而已
      • self表示当前对象,谁调用该方法就表示谁,哪个对象调用就表示哪个对象
      • 通过self可以访问成员属性,也可以调用成员方法
  • __str__方法

    • 示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      class Person:
      # 使用print函数打印时,默认打印对象所属的类型及对象的地址
      # 该函数要求返回一个字符串,当对象作为print参数打印时会打印该字符串
      def __str__(self):
      # 要求返回一个字符串
      return '我叫{},今年{}'.format(self.name, self.age)


      xiaoming = Person()
      xiaoming.name = 'xiaoming'
      xiaoming.age = 18

      print(xiaoming)
    • 练习:

      • 自定义一个狗类,完成属性的动态添加,方法的调用
        • 属性:名字、年龄、颜色
        • 方法:跑、吃、游泳、叫
  • 构造方法

    • 作用:用于对象创建后初始化相关的属性
    • 示例:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      class Cat:
      def __init__(self, name, age):
      # 创建对象后进行初始化操作,系统会自动调用
      # 也叫构造方法
      print('init')
      self.name = name
      self.age = age
      self.color = '白色'


      # 创建对象时的参数要与构造方法一致
      tom = Cat('Tom', 1)
      print(tom)
  • 析构方法

    • 作用:当对象即将销毁时,系统会自动调用
    • 示例1:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      import time


      class Pig:
      def __del__(self):
      # 当对象释放时系统会自动调用,如果你使用del删除对象,则立即释放调用该方法
      # 一般在此处做:断开连接、关闭文件、释放资源等
      print('大师兄,我不行了')


      bajie = Pig()

      # 若删除对象,则会立即调用析构方法
      del bajie

      time.sleep(5)
      bajie.name = 'wuneng'
  • 示例2:小明手里有两张牌,左手♥K,右手♠A,问:小明交换两手的牌后,手里分别是什么?
  • 思路:
    • 先找到对象:小明、左手、♥K、♠A、右手
    • 根据对象抽象出来的类:人、牌、手
    • 写出对应的逻辑,反过来完善抽象出来的类
    • 按照题目要求创建对应的对象,调用相关的方法
    • 代码:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      # 扑克牌
      class Poker:
      def __init__(self, color, number):
      self.color = color
      self.number = number

      def __str__(self):
      return '{}{}'.format(self.color, self.number)


      # 创建两张牌
      p1 = Poker('♥', 'K')
      p2 = Poker('♠', 'A')


      # 手的类
      class Hand:
      def __init__(self, poker=None):
      self.poker = poker

      def hold_poker(self, poker):
      self.poker = poker


      # 创建左右两只手的对象
      left_hand = Hand(p1)
      right_hand = Hand(p2)


      # 人的类
      class Person:
      def __init__(self, name, left_hand, right_hand):
      self.name = name
      self.left_hand = left_hand
      self.right_hand = right_hand

      # 展示手里的牌
      def show(self):
      print('{}张开手'.format(self.name))
      print('左手:{}'.format(self.left_hand.poker))
      print('右手:{}'.format(self.right_hand.poker))

      # 交换手里的牌
      def swap(self):
      self.left_hand.poker, self.right_hand.poker = self.right_hand.poker, self.left_hand.poker
      print('{}交换两手的牌'.format(self.name))


      # 创建小明对象
      xiaoming = Person('小明', left_hand, right_hand)
      # 展示手里的牌
      xiaoming.show()
      # 小明交换牌
      xiaoming.swap()
      # 再次展示手里的牌
      xiaoming.show()

常见的内置函数

  • 内置函数:在类的内部,特定时机自动触发的函数
  • 示例:setattr、getattrr、delattr
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    class Person:
    # def __init__(self, name):
    # self.name = name

    def __setattr__(self, key, value):
    # 当设置对象成员属性时,系统会自动调用
    print(key, value)
    self.__dict__[key] = value

    def __getattr__(self, item):
    # 当访问不存在的属性时,系统会自动调用
    if item == 'age':
    return 123
    else:
    return 'default'

    def __delattr__(self, item):
    # 当销毁对象的成员属性时,系统会自动调用
    print('del', item)


    xiaoming = Person()

    # 每个对象都有一个成员属性:__dict__
    # 用于存放对象的属性,包括动态添加的
    # print(xiaoming.__dict__)

    # xiaoming.name = '小明'
    # print(xiaoming.name)

    # print(xiaoming.__dict__)

    xiaoming.age = 18

    print(xiaoming.age)
    print(xiaoming.hello)

    del xiaoming.age
    # del xiaoming.hello
  • 练习:

    1
    2
    自己研究:setitem、getitem、delitem
    友情提醒:当将一个对象作为字典操作时,会触发上面对应的方法