面向对象--第一部分

面向对象

面向对象

  • 与面向过程对比

    • 面向过程:数学逻辑的映射,学会做个好员工。

    • 面向对象:生活逻辑的映射,学会做个好领导。

  • 生活实例

    • 类: 手机 电脑

    • 对象: 习大大、普京 二狗的iphoneX 生辉桌上的电脑

  • 官方定义

    • 类:具有相同特征(属性和行为)事物的抽象

    • 对象:某个类的具象

  • 编程语言

    • 类:是一种自定义的数据类型

    • 对象:某个类类型的变量

面向对象语法

  • 类的定义

    class 类名:
    pass
  • 语法说明

    • 定义类需要使用关键字class

    • 类名:原则上符合标识符命名规范即可,但是通常我们都采用大驼峰风格命名,如:UserName

    • 类名后面的':'不要忘记

    • 类的内容要进行整体缩进

    • 行为通过方法体现

    • 属性通过变量体现,需要动态添加

    • 成员访问:

      • 属性:对象.属性名

      • 方法:对象.方法名()

    • 示例:

      # 定义类
      class Person:
          # 行为时通过方法体现的
      # 吃饭
          def eat(self):
              print('红烧鸡腿我喜欢吃')
      ​
          # 睡觉
          def sleep(self):
              print('睡觉是一种生活态度')
              
      # 创建对象
      hui = Person()
      ​
      # 属性时动态添加的
      hui.age = 30
      hui.height = 170
      print(hui.age)
      ​
      # 调用对象方法
      hui.eat()
  • self使用

    class Person:
        def run(self):
            # self表示当前对象,就是调用该方法的对象
            print('{}每天以2m/s的速度慢跑5km'.format(self.name))
    ​
        def introduce(self):
            # 不但可以访问成员属性
            print('我叫{}今年18岁'.format(self.name))
            # 还可以调用成员方法
            # self参数可以使用其他名字,调用方法时不需要传递
            self.run()
    ​
    hui = Person()
    hui.name = '生辉'
    # hui.run()
    ​
    fei = Person()
    fei.name = '赵飞'
    # fei.run()
    fei.introduce()      
  • __str__方法

    class Person:
          # 默认打印对象,显示类名+地址
          # 重写该方法,打印该方法的返回值
          def __str__(self):
              return '我叫{},今年{}岁'.format(self.name, self.age)
    ​
      james = Person()
      james.name = '勒布朗.詹姆斯'
      james.age = 33
      print(james)
  • __init__方法        

    class Cat:
        def __str__(self):
            return 'name:{},age:{},color:{}'.format(self.name, self.age, self.color)
    ​
        # 构造方法:创建对象后,会自动调用该方法完成初始化设置
        def __init__(self, name, age, color):
            # print('__init__', name, age, color)
            self.name = name
            self.age = age
            self.color = color
    ​
    # 这种方案比较繁琐
    # jiafei = Cat()
    # jiafei.name = '加菲'
    # jiafei.age = 2
    # jiafei.color = '橘黄色'
    # print(jiafei)
    ​
    jiafei = Cat('加菲', 2, '橘黄色')
    print(jiafei)
  • __del__方法

    class Pig:
          # 析构方法:当对象释放时,系统会自动调用
          # 若手动使用del删除:则会立即调用该方法
          # 该方法一般做资源释放操作,如:数据库断开连接,文件关闭
          def __del__(self):
              print('大师兄,我不行了')
    ​
      bajie = Pig()
      del bajie
      print('八戒,一路走好')
  • 思考:小明手里有2张牌,左手♥K,右手♠A,小明交换两手的牌后,手里分别有什么?

    • 先找到对象:小明、左手、右手、♥K、♠A

    • 根据对象抽象类:人、手、牌

    • 根据需求完善设计对应的类

    • 示例

      # 扑克牌
      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), end=' ')
              print('左手:{}'.format(self.left_hand.poker), end=',')
              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()
  • 练习:设计一个数学类,属性有两个数,方法:加、减、乘、除,展示成员

    第一种:
    class Math:
        def __init__(self,one,two):
            self.one = one
            self.two = two
        def add(self):
            print('{}+{}'.format(self.one,self.two))
        def sub(self):
            print('{}-{}'.format(self.one, self.two))
        def mul(self):
            print('{}*{}'.format(self.one, self.two))
        def div(self):
            print('{}/{}'.format(self.one, self.two))
    show = Math(10,5)
    show.add()
    show.mul()
    show.div()
    show.sub()
    第二种:
    class Number:
        def __init__(self,num1,num2):
            self.num1 = num1
            self.num2 =num2【
        def add(self):
            return self.num1 + self.num2
    ​
        def sub(self):
            return self.num1 - self.num2
    ​
        def mul(self):
            return self.num1 * self.num2
    ​
        def div(self):
            if self.num2 == 0:
                return None
            return self.num1 / self.num2
    a = Number(3,3)
    print(a.add())
    print(a.sub())
    print(a.mul())
    print(a.div())
  • 实现平方和

    #对外提供简单易用的接口
    class Number:
        def __init__(self,num1,num2):
            self.num1 = num1
            self.num2 =num2
        def add(self):
            return self.num1 + self.num2
    ​
        def sub(self):
            return self.num1 - self.num2
    ​
        def mul(self):
            return self.num1 * self.num2
    ​
        def div(self):
            if self.num2 == 0:
                return None
            return self.num1 / self.num2
        @classmethod
        def pingfanghe(cls,num1,num2):
            a = cls(num1,num1)
            m = a.mul()
            b = cls(num2,num2)
            n = b.mul()
            c = cls(m,n)
            ret = c.add()
            return ret
    ret = Number.pingfanghe(2,3)
    print(ret)

常用内置函数

  • 内置函数:在类中,特定时机自动回触发的函数。

    • 设置、获取、销毁属性时自动触发的方法:

      class Person:
          def __str__(self):
              return '姓名:{}'.format(self.name)
      ​
          def __init__(self, name):
              self.name = name
      ​
          def __del__(self):
              print('对象即将销毁')
      ​
          # 当访问不存在的属性时会自动触发该方法
          def __getattr__(self, item):
              if item == 'age':
                  return 18
              else:
                  return '你猜'# 设置属性时会自动触发该方法
          def __setattr__(self, key, value):
              # print(key, value)
              self.__dict__[key] = value
      ​
          # 销毁对象的指定属性时会自动触发
          def __delattr__(self, item):
              print(item, '属性即将销毁')
              
      xiaoming = Person('小明')  
      ​
      # print(xiaoming.age)
      # print(xiaoming.weight)
      xiaoming.age = 20# 存放了所有的对象属性
      # print(xiaoming.__dict__)
      # print(xiaoming.age)
      del xiaoming.age
  • 将对象当做字典操作,特定时机自动触发的函数

    class Person:
        # 将对象当做字典操作,添加或设置属性时自动触发
        def __setitem__(self, key, value):
            print(key, value)
            self.__dict__[key] = value
    ​
        # 将对象当做字典操作,获取属性时自动触发
        def __getitem__(self, item):
            # print(item)
            return self.__dict__.get(item)
    ​
        # 将对象当作字典操作,销毁属性时自动触发
        def __delitem__(self, key):
            print(key, '即将销毁')
            del self.__dict__[key]
    ​
    xiaoming = Person()
    ​
    xiaoming['name'] = '小明'
    # print(xiaoming.name)
    print(xiaoming['name'])
    ​
    del xiaoming['name']
  • 将对象当做函数调用

    class Person:
        # 将对象当做函数调用时,会自动触发该方法
        def __call__(self, *args, **kwargs):
            # print('__call__', args)
            return sum(args)
    ​
    xiaoming = Person()
    # 如果想这样调用,必须重写__call__方法
    ret = xiaoming(1, 2, 3)
    print(ret)
  • 判断一个对象是否可以调用,是否拥有某属性,是否是函数

    def test():
        pass# 判断一个对象能否被调用
    print(callable(xiaoming))
    print(callable(test))
    ​
    # 判断一个对象是否拥有__call__属性
    print(hasattr(test, '__call__'))
    print(hasattr(xiaoming, '__call__'))
    ​
    # 判断一个对象是否是函数
    from inspect import isfunction
    print(isfunction(test))
    print(isfunction(xiaoming))

练习

  • 第一题

    • 设计一个学生类

      • 属性:姓名、学号、年龄、成绩

    • 设计一个班级类

      • 属性:班级代号,所有学生

    • 要求:实现向班级中添加学生、删除学生、查看学生、按照指定条件排序

      #学生类
      class Student :
      ​
          def __init__(self,name,number,age,grade):
              self.name = name
              self.number = number
              self.age =age
              self.grade = grade
          def __str__(self):
              return 'name:{},number:{},age:{},grade:{}'.format(self.name,self.number,self.age,self.grade)
      ​
      #班级类
      class Class :
          def __init__(self,title):
              self.title =title
              self.student_list = []
              self.student_dict = {}
          def add_stu(self,stu):
              self.student_list.append(stu)
              self.student_dict[stu.number] = stu
          #学生排序
          def sort_stu(self,key=None,reverse =False ):
              self.student_list.sort(key=key , reverse=reverse)
          #查找学生
          def get_stu(self,number):
              return self.student_dict.get(number)
          #删除学生
          def del_stu(self,number):
              #从字典中弹出并删除
              s = self.student_dict.pop(number)
              #从列表删除
              self.student_list.remove(s)
          def show_stu(self):
              for stu in self.student_list:
                  print(stu)
      ​
      from  random import randint
      #创建一个班级
      banji = Class('python-1805')
      #按照成绩
      banji.sort_stu(key=lambda  banji: banji.grade,reverse=True)
      for i in range(10):
          name = 'stu' + str(i+1)
          number = 100 + i
          age = randint(20,30)
          grade = randint(0,100)
          #创建学生对象
          stu = Student(name,number,age,grade)
          #将学生添加到班级的列表中
          banji.add_stu(stu)
      ​
      banji.show_stu()
  • 第二题

    • 将歌词解析封装成类,要求:提供一个方法(根据时间返回歌词)

      • 提示:封装两个类:歌词类、歌词管理类

        #歌词类
        class Lrc:
            def __init__(self,sec,lrc):
                self.sec = sec
                self.lrc = lrc
            def __str__(self):
                return "{}:{}".format(self.sec,self.lrc)
          #歌词管理类
          class LrcManager:
              def __init__(self,lrc_file):
                  self.lrc_dict = {}
                  self.time_list = []
                  self.song_dict = {}
                  self.lrc_file =lrc_file
                  self.jiexi = ()
        ​
              def jiexi(self):
                  fp = open(self.lrc_file)
                  lrc_list = fp.readlines()
              #根据时间返回歌词对象
              def get_lrc(self,sec):
                  for t in self.time_list:
                      if t <sec:
                          return self.lrc_dict[t]

猜你喜欢

转载自www.cnblogs.com/542684416-qq/p/9807110.html