• PYTHON1.面向对象_day02


    课程:Python面向对象
    进度:day2

    上次内容回顾
    1. 面向对象:以对象为中心
    2. 三大特性:封装、继承、多态
    3. 如何定义类、如何实现继承
         class 类名称(父类列表):
               # 构造函数
               # 其它成员函数

    今天的内容
    1. 多态:相同的方法,不同的表现(重点)
        1)事物除了共性外,还具有各自的特性(个性)
             多态就用来处理事物的个性
        2)多态能够在不影响父类行为(不修改父类代码)
             情况下,进行功能的扩展和变更
        3)使程序(软件设计)更具灵活性

    2. 方法的重写:父类中定义过的方法子类中重新定义
        (重点)

    3. 多态的实现:通过在子类中重写父类的方法实现多态(重点)
        (重点)
       
    课堂练习:
    编写一个手机类(Phone)
    属性:名称(name), 价格(price),
               CPU, 屏幕尺寸( screen_size)
    方法:开机(startup),关机(shutdown)
               打电话(call), 发短信(send_msg)
    并编写测试代码
    见 phone.py

      1 # phone.py
      2 # 手机类
      3 import time
      4 class Phone:
      5     def __init__(self, name, price,
      6                  CPU, screen_size):
      7         self.name = name
      8         self.price = price
      9         self.CPU = CPU
     10         self.screen_size = screen_size
     11 
     12     def startup(self):
     13         print("正在开机")
     14         time.sleep(2)
     15         print("开机成功")
     16 
     17     def shutdown(self):
     18         print("正在关机")
     19         time.sleep(2)
     20         print("关机成功")
     21 
     22     def call(self, phone_no):
     23         print("正在拨号")
     24         time.sleep(1)
     25         print("正在和%s通话" % phone_no)
     26 
     27     def send_msg(self, phone_no, msg):
     28         print("正在向%s发送信息..." % phone_no)
     29         time.sleep(2)
     30         print("【%s】发送成功" % msg)
     31 
     32     def __del__(self):  # 析构方法
     33         print("__del__方法被调用")
     34 
     35 def fun():
     36     phone = Phone("华为",1999.99,
     37                  "双核2G", 5.5)
     38     print("fun()函数退出")
     39 
     40 if __name__ == "__main__":
     41     myphone = Phone("华为",1999.99,
     42                     "双核2G", 5.5)
     43     fun()
     44     print("程序退出")
     45     # myphone程序退出时被销毁
     46 
     47 
     48 
     49     myphone.startup()  #启动
     50     myphone.call("13512345678") #打电话
     51     myphone.send_msg("13512345678","你好")
     52     myphone.shutdown()  #关机
    phone.py

    phone

    4. 面向对象的技术特性
       1)构造和析构
          a)构造方法(重点)
            - 名称:在Python中,固定为__init__
            - 作用:是为对象创建属性,并且赋予初始值
            - 调用时机:对象被创建(实例化)自动调用
            - 如果在类中未定义,Python会给出默认的构造方法
            - 在继承关系中,如果父类定义了__init__方法
              在子类的构造方法中,必须要调用父类的构造方法

           b)析构方法
              - 名称:__del__
              - 调用时机: 对象被销毁时自动调用
                                   del obj, 局部变量退出作用于,程序退出
              - 作用:对象销毁时,执行清理操作

       2)多重继承:一个类有多个父类
           - 如何实现多继承: 定义类的时候,继承自多个父类,
                 父类之间用逗号隔开
           - 语法格式:
                 class 类名称(父类1, 父类2, ......):
                         语句块

           - 通过多重继承,子类具有所有父类的特征和行为
           - 如果多个父类具有相同的方法(或属性名称),通过
             类的__mro__属性中记录的顺序进行方法查找

            MRO(Method Resolution Order)

            总的原则按照由下至上、从左至右(继承列表中前后)
             进行查找,直到object类,如果都没有找到就报错

      1 # mul_inh.py
      2 # 多重继承示例
      3 # 超人类继承自战士、飞行者、喷或者
      4 # 三个类
      5 class Fighter:  #战士类,默认继承自object
      6     def fight(self):
      7         print("我能战斗")
      8 
      9     def roar(self):  #吼叫
     10         print("战士吼叫:嗷嗷嗷")
     11 
     12 class Flyer:  #飞行者类
     13     def fly(self):
     14         print("我能飞行")
     15 
     16     def roar(self):  #吼叫
     17         print("飞行者吼叫:呜呜呜")
     18 
     19 class Firer: # 喷火者
     20     def fire(self):
     21         print("我能喷火")
     22 
     23 # 超人类,继承自Fighter,Flyer,Firer父类
     24 class SuperMan(Flyer,Fighter,Firer):
     25     pass
     26 
     27 if __name__ == "__main__":
     28     super_man = SuperMan() # 实例化超人对象
     29     super_man.fight()  # 超人战斗
     30     super_man.fly()    # 超人飞行
     31     super_man.fire()   # 超人喷火
     32     super_man.roar()   # 超人吼叫??
     33     # Mehtod Resolution Order
     34     # 决定调用哪一个类的方法
     35     # print(SuperMan.__mro__)
     36     print(SuperMan.__bases__) # __bases__绑定父类
     37     print(Fighter.__base__)
     38     print(Flyer.__base__)
     39 
    mul_inh.py

    mul  

    3)object类:所有类的总父类,如果定义类时候,没有
           指定父类,则默认从object类继承

                             
           类的父类可以通过__base__属性查看

       4)super()和issubclass()
          - super()函数
            作用:返回绑定的父类
                  有时候需要显式调用父类方法
                  就使用super()函数
            格式:super(type, ojb) 返回obj对象父类
                  super() 返回当前对象父类

                          只能在类的方法中调用

         - issubclass: 判断一个类是否是另一个
                        类的子类,如果是返回True
                        如果不是返回False
            格式:issubclass(cls, class_or_tuple)
            
    5. 函数重写(重点,理解原理)
       1)对象转字符函数的重写
         - str:将对象转换成人阅读的字符串
                重写__str__()

         - repr: 返回字符串,给Python解释器阅读
                 通过eval(repr(obj))能够还原obj
                 对象,重写__repr__()

         - 当调用str(obj)将对象转换成字符串
           时,其搜索顺序为:
           + 优先查找obj.__str__()方法(包括父类)
           + 如果上一步不存在,则调用obj.__repr__()
           + 如果上一步不存在,则调用object.__repr__()

      1 
      2 class A:
      3     def __init__(self, name):
      4         self.name = name
      5 
      6     def __str__(self):  # 重写__str__函数
      7         return "name = %s" % self.name
      8 
      9 class B(A):
     10     def __init__(self, name, id):
     11         super().__init__(name) # 调用父类构造方法
     12         self.id = id  # id属性被创建
     13 
     14     def __repr__(self):  # 重写__repr__方法
     15         # 返回例如"B('Jerry','0001')"
     16         return "B('%s','%s')" % (self.name, self.id)
     17 
     18     def __str__(self):  # 重写__str__函数
     19         return "name=%s,id=%s"%(self.name,self.id)
     20 
     21 b = B("Jerry", "0001")  # ==》
     22 print(b)
     23 
     24 # str_obj = repr(b)
     25 # print(str_obj)
     26 # new_obj = eval(str_obj)  # 通过调用eval函数还原对象
     27 # print(new_obj)
     28 
     29 # print(b)  # B类中重写__str__方法,所以可以直接打印
     30 # str_obj = str(b)  # 将b对象转换成字符串
     31 # print(str_obj)
     32 
     33 #super(B, b).print() # 根据对象b找到父类,并调用父类的print
     34 # print(issubclass(B, (A,object)))    # True
     35 # print(issubclass(B,object)) # True
     36 # print(issubclass(A, B))  # False
    a.py

      2)内建函数重写
         - abs()函数:重写__abs__()
         - len()函数: 重写__len__()
         - reversed()函数: 重写__reversed__()
         - round()函数:重写__round__()
        
         课堂练习:重写__len__()和__round__()
                   重写__reversed__()
         示例见my_list.py

      1 # mylist.py
      2 # 自定义列表
      3 class MyList:
      4     def __init__(self, iterable=[]):
      5         self.data = [x for x in iterable]
      6 
      7     # 重写__abs__()函数
      8     def __abs__(self):
      9         #对每个元素求绝对值,用产生的结果实例化一个MyList对象
     10         return MyList(abs(x) for x in self.data)
     11 
     12     def __str__(self):  # 重写__str__()函数
     13         ret = ""
     14         for x in self.data:
     15             ret += str(x)  # 将元素由数字转换成字符串
     16             ret += " "
     17         return ret   # 返回结果串
     18 
     19     def __len__(self):  # 重写__len__函数,返回元素个数
     20         return len(self.data)
     21 
     22     # 对每个元素求近似值,并实例化对象返回
     23     def __round__(self):
     24         return MyList(round(x,2) for x in self.data)
     25 
     26     # 重写__reversed__,倒序
     27     def __reversed__(self):
     28         tmp = []
     29         x = len(self.data) - 1  # 最后元素下标
     30         while x >= 0:
     31             tmp.append(self.data[x])
     32             x -= 1   # 计数器减1
     33         return MyList(tmp)  # tmp是经过倒序的可迭代对象
     34 
     35     def __add__(self, other): # L1 + L2
     36         return MyList(self.data + other.data)
     37 
     38     def __mul__(self, value): # L1 * 2
     39         return MyList(self.data * value)
     40 
     41     def __eq__(self, other): # 重载==运算符
     42         len1 = len(self.data)  # 取data属性长度
     43         len2 = len(other.data) # 取另一个对象data的长度
     44         if len1 != len2: # 长度不相等,无需比较
     45             return False
     46 
     47         for i in range(0, len1):
     48             if self.data[i] != other.data[i]:
     49                 return False #只要出现元素不相等,返回False
     50         return True
     51 
     52     def __ne__(self, other): # 重载!=运算符
     53         return not (self == other)
     54 
     55     def __gt__(self, other):
     56         len1 = len(self.data)  # 取data属性长度
     57         len2 = len(other.data) # 取另一个对象data的长度
     58         min_len = min(len1, len2) # 获得循环上限
     59 
     60         for i in range(min_len): # 以长度短的作为循环上限
     61             if self.data[i] == other.data[i]:
     62                 continue
     63             elif self.data[i] > other.data[i]:
     64                 return True
     65             elif self.data[i] < other.data[i]:
     66                 return False
     67         if len1 == len2:  #相等
     68             return False
     69         elif len1 > len2: #前面的元素相等,长度比对方大
     70             return True
     71         else:
     72             return False
     73 
     74     def __neg__(self): #重载符号运算符
     75         return MyList(-x for x in self.data)
     76 
     77     def __contains__(self, e): # in/not in运算符重载
     78         print("__contains__()被调用")
     79         return e in self.data
     80 
     81     def __getitem__(self, i): # 重载[]取值操作
     82         return self.data[i]
     83 
     84     def __setitem__(self, i, value):#重载[]赋值操作
     85         self.data[i] = value
     86 
     87     def __delitem__(self, i): #重载[]删除操作
     88         del self.data[i]
     89 
     90 if __name__ == "__main__":
     91     L = MyList([-1, 2, -3, 4, -5])
     92     print(L[0])  # 索引取值
     93     L[2] = 333   # 通过索引设置值
     94     print(L)
     95     del L[3]     # 删除
     96     print(L)
     97 
     98     # print(2 in L)   # True
     99     # print(4 not in L) # False
    100 
    101     #print(-L)  # 对对象执行负号运算
    102 
    103     # L1 = MyList([1,3,5])
    104     # L2 = MyList([1,3,5,7])
    105     # print(L1 > L2)
    106     # L = MyList([-1, 2, -3, 5.6789])
    107     # L3 = MyList([3,4,5])
    108     # print(L + L3)
    109     # print(L * 2)
    110     # print(2 * L)
    111 
    112     # print(reversed(L))  # 对象元素逆序并打印
    113     # print(len(L))   # 打印返回的长度
    114     # print(round(L)) # 打印新产生的对象
    115     #                 # 每个元素都是原对象元素的近似值
    116     # L2 = abs(L)  # 重写了__abs__()函数,支持abs表达式
    117     # print(L2)  # 重写了__str__()函数,所以支持print()
    my_list.py

       3)数值转换函数重写
         - int(): 重写__int__()
         - float(): 重写__float__()
         - complex(): 重写__complex__()
         - bool: 重写__bool__()
         示例见my_number.py

      1 # my_number.py
      2 # 自定义数字类型
      3 # 数值转换函数重写示例
      4 class MyNumber:
      5     def __init__(self, value):
      6         self.data = value #值,字符串
      7 
      8     def __int__(self):
      9         return int(float(self.data))
     10 
     11     def __float__(self):
     12         return float(self.data)
     13 
     14     def __complex__(self):
     15         return complex(self.data)
     16 
     17 if __name__ == "__main__":
     18     num = MyNumber("123.45")
     19     print(getattr(num, "data")) # "123.45"
     20     print(num.data)  # "123.45"
     21 
     22     setattr(num, "data", "456.78")
     23     print(getattr(num, "data")) #456.78
     24 
     25     print(hasattr(num, "data")) #True
     26     print(hasattr(num, "aaaa")) #False
     27 
     28     delattr(num, "data") #删除data属性
     29     print(hasattr(num, "data")) #False
     30 
     31     # print(int(num))  #将num对象转换成int
     32     # print(float(num))
     33     # print(complex(num))
    my_number.py

    my_number

    6. 属性管理函数:操作对象属性
       1)getattr: 获取对象属性值
         - 格式: getattr(obj, name[,default])
         - 作用: getattr(x, "y") 等同于
                  x.y表达式
                 
       2)setattr: 设置对象属性值
         - 格式:setattr(obj, name, value)
         - 作用:setattr(x, "y", "zzz")等同于
                 x.y = "zzz"表达式   
        
       3)hasattr: 判断有没有某个属性值
         - 格式:hasattr(obj, name)
         - 返回:布尔类型,有-True 没有-False
      
       4)delattr: 删除对象某个属性值
         - 格式:delattr(obj, name)
         - 作用:delattr(x, "y")等同于
                 del x.y 表达式

    作业:
    1)编写一个账户类(Account)
        属性:账号(acct_no), 户名(acct_name),
              开户日期(reg_date),
              账户类型(acct_type)(借记卡/贷记卡),
              状态(acct_status)(正常,挂失,冻结,注销)
              余额(balance)
        方法:存款(diposite)
              取款(draw)
              冻结(freeze), 解冻(unfreeze)
              挂失(report_loss),解挂失(relieve_loss)
              修改账户信息(modify_acct_info)
    2)编写测试代码

      1 # account.py
      2 # 账户类
      3 dict_status = {  #状态字典
      4   0:"正常",1:"冻结",2:"挂失",3:"销户"
      5 }
      6 dict_type = {0:"借记账户", 1:"贷记账户"}
      7 
      8 class Account:
      9     def __init__(self, acct_no, acct_name,
     10                  reg_date, acct_type,
     11                  acct_status, balance):
     12         self.acct_no = acct_no #账号
     13         self.acct_name = acct_name #户名
     14         self.reg_date = reg_date #开户日期
     15         self.acct_type = acct_type #类型
     16         self.acct_status = acct_status #状态
     17         self.balance = balance #余额
     18 
     19     def diposite(self, amt): #存款
     20         print("存款前余额:%.2f"%self.balance)
     21         self.balance += amt #修改余额
     22         print("存款后余额:%.2f"%self.balance)
     23 
     24     def draw(self, amt): #取款
     25         if self.acct_status == 0: #正常
     26             if self.balance < amt: #余额不足
     27                 print("余额不足")
     28                 return
     29             else:  #余额充足
     30                 print("取款前余额:%.2f" % self.balance)
     31                 self.balance -= amt #修改余额
     32                 print("取款后余额:%.2f" % self.balance)
     33         else:  #非正常状态
     34             print("状态不允许取款")
     35 
     36     def freeze(self): # 冻结
     37         if self.acct_status != 0:
     38             print("状态不允许冻结")
     39             return
     40         self.acct_status = 1 #状态置为冻结
     41         print("账户已冻结")
     42 
     43     def unfreeze(self): #解冻
     44         if self.acct_status != 1: #判断已冻结
     45             print("状态不允许解冻")
     46             return
     47         self.acct_status = 0 #状态置为正常
     48         print("账户已解冻")
     49 
     50     def __str__(self): #重写__str__()
     51         # 将状态转换为对应的字符串
     52         status = dict_status[self.acct_status]
     53         # 将类型转换为对应的字符串
     54         type = dict_type[self.acct_type]
     55         ret="账号:%s,户名:%s,开户日期:%s,类型:%s,状态:%s,余额:%.2f"
     56             %(self.acct_no, self.acct_name, 
     57              self.reg_date, type, 
     58              status, self.balance)
     59         return ret
     60 
     61 if __name__ == "__main__":
     62     acct = Account("6223450001", "张大大",
     63                    "2018-01-01", 0, 0, 2000.00)
     64     acct.diposite(1000.00)  #存款
     65     acct.draw(500)  #取款
     66     print(acct)  #打印账户信息
     67     acct.freeze() #冻结
     68     print(acct)  #打印账户信息
     69     acct.unfreeze() #解冻
     70     print(acct)  #打印账户信息
     71 
     72 
     73 
     74 
    account.py

    acct

  • 相关阅读:
    ASP.net 上传
    asp.net 上传
    asp.net dropdownlist和listbox
    jqeury之平移轮播
    vs2013的asp.net 管理
    jqeury轮播
    jqeury之轮播图
    重温委托(delegate)和事件(event)
    Log4Net
    解决SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问的方法
  • 原文地址:https://www.cnblogs.com/shengjia/p/10386957.html
Copyright © 2020-2023  润新知