PYTHON1.面向对象_day03

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

上次内容回顾
1. 多态
   1)什么是多态:同一个方法,在不同
      子类中有不同的表现
   2)方法的重写来实现
   3)保持程序的扩展性、灵活性
  
2. 面向对象的技术特性
   1)构造方法与析构方法
     a)构造:__init__()
        调用时机:对象被创建时自动调用
        作用:创建对象属性,并赋值
        注意:子类构造方法显示调用父类构造
              方法
     b)析构方法:__del__()
        调用时机:对象被销毁时调用
        作用:对象销毁时执行清理操作
       
   2)object类:所有类最终的父类
                如果类定义时没有指定父类
                默认从object中继承
                __base__查看父类
  3)super()和issubclass()函数
      super(): 获得父类的绑定
      两种格式:super()  只能在类方法中使用
                super(type, obj) obj必须是type示例化的对象
     
      issubclass():判断某个是不是另一个类的子类
      格式:issubclass(cls, cls_or_tuple)

  4)多重继承:一个类有多个父类
      MRO: 方法解析顺序,__mro__
           从下至上,从左至右
          
3. 函数重写:让对象操作更方便
   1)对象转字符串函数
     str(): __str__(),返回字符串给人阅读
     repr():__repr__(),返回字符串给解释器阅读
 
   2)内建函数
     abs(): __abs__()
     len(): __len__()
     reversed(): __reversed()__
     round():__round()__
    
   3)数值转换函数
     int(): __int__()
     float(): __float__()
     complex(): __complex__()
     bool(): __bool__()
    
4. 属性操作函数
   getattr(obj, name):获取对象属性
   setattr(obj, name, value):设置某个属性值
   hasattr(obj, name):判断对象有没有某个属性
   delattr(obj, name):删除某个属性值
  
作业:见account.py


今天内容
1. 可迭代对象
   1)什么是迭代器
   2)代码特征:重写__iter__()方法返回可迭代对象
                重写__next__()方法获取下一个元素
   3)__next__()方法,实现迭代器协议
      如果有下一个元素,则返回
      如果没有下一个元素,抛出StopIteration异常
   4)示例:见myiter.py

PYTHON1.面向对象_day03
  1 # myiter.py
  2 # 通过函数重写,实现自定义迭代器
  3 class MyIter:
  4     #用列表初始化对象
  5     def __init__(self, lst):
  6         self.data = lst #lst是列表
  7         self.cur_index = 0 #计数器
  8 
  9     def __iter__(self):# 返回可迭代对象
 10         return MyIter(self.data)
 11 
 12     def __next__(self):# 获取下一个元素
 13         if self.cur_index >= len(self.data):
 14             raise StopIteration #抛出异常
 15         else:
 16             i = self.cur_index #记录计数器
 17             self.cur_index += 1 #计数器加1
 18             return self.data[i] #返回元素
 19 
 20 if __name__ == "__main__":
 21     myiter = MyIter(range(1,10))
 22     for x in myiter:
 23         print(x, end=" ")
 24 
myiter.py

PYTHON1.面向对象_day03

2. 运算符重载
   1)什么是运算重载:自定义类中,重写
     某些方法,重写后就可以对对象进行
     某些运算符操作
   2)目的
      a)简化对象操作。例如:
        c = "abc" + "123"
        d = "123" > "456"
      b)代码清晰、直观
      c)可以在类中自定义运算规则    
      注意:运算重载不要改变原有意义
 
   3)算术运算符重载
     - 重写方法后,支持+,-,*,//,/,%,**
     - 重载方法和运算符的对应关系
       __add__(self,rhs)   self + rhs
       __sub__(self,rhs)   self - rhs
       __mul__(self,rhs)   self * rhs
       __truediv__(self,rhs)   self / rhs
       __floordiv__(self,rhs)  self // rhs
       __mod__(self,rhs)       self % rhs
       __pow__(self,rhs)       self ** rhs

  
   课堂练习:在MyList类中,重载+,*运算符
           L1 = MyList([1,2,3])
           L2 = MyList([4,5,6])
           L1 + L2==>MyList([1,2,3,4,5,6])
           L1*2 ==> MyList([1,2,3,1,2,3])
           见mylist.py
          
     4)反向算术运算符重载
        在正向运算符重载的函数前面加r
        例如:__radd__(), __rsub__()...
        支持:2 + obj (对象在操作符右边)

    5)复合运算操作符
        在正向运算符重载的方法前加i前缀
        例如:__iadd__(), __isub__()...
        重载运算符后,执行复合表达式
        ojb += 2,首先查找__iadd__(),
        如果没有找到,则再查找__add__(),
        如果再没有找到,报TypeError异常
       
     6)比较运算符:>,<,>=,<=,==,!=
       - 重写方法和运算符的对照关系
         __lt__(self, rhs)   self < rhs
         __gt__(self, rhs)   self > rhs
         __eq__(self, rhs)   self == rhs
         __ne__(self, rhs)   self != rhs
         __ge__(self, rhs)   self >= rhs
         __le__(self, rhs)   self <= rhs

       - 示例:见truck.py

PYTHON1.面向对象_day03
  1 # truck.py
  2 # 卡车类,演示运算符重载
  3 class Truck:
  4     def __init__(self, load):
  5         self.load = load #载重
  6 
  7     def __add__(self, value):#重载+运算符
  8         print("__add__()被调用")
  9         return Truck(self.load + value)
 10 
 11     def __mul__(self, value): #重载*运算符
 12         return Truck(self.load * value)
 13 
 14     #反向+运算符重载,支持 3 + truck操作
 15     def __radd__(self, value):
 16         print("__radd__()被调用")
 17         return Truck(self.load + value)
 18 
 19     # 符合运算符重载,支持obj += 2表达式
 20     # def __iadd__(self, value):
 21     #     print("__iadd__()被调用")
 22     #     return Truck(self.load + value)
 23 
 24     def __str__(self):
 25         return "load: %d" % self.load
 26 
 27     def __gt__(self, other): # 重载>运算符
 28         print("__gt__()方法被调用")
 29         if self.load > other.load:
 30             return True
 31         else:
 32             return False
 33 
 34     # def __lt__(self, other): # 重载<运算符
 35     #     if self.load < other.load:
 36     #         return True
 37     #     else:
 38     #         return False
 39 
 40 if __name__ == "__main__":
 41     t1 = Truck(20)
 42     t2 = Truck(25)
 43     print(t1 > t2)  # 调用__gt__()
 44     print(t1 < t2)  # 调用__lt__()
 45     #t = Truck(20)
 46     #t2 = t + 1 # t2接受返回的对象
 47     #t2 = 1 + t  # 调用__radd__()方法
 48     # t += 1 # 调用__iadd__()方法,如果没有该方法,调用__add__
 49     # print(t)
 50     # t3 = t * 4
 51     # print(t3)
truck.pyPYTHON1.面向对象_day03
       - 比较规则:
         >: 首先找__gt__(), 没有找__lt__()
            并将执行__lt__()结果取反
            如果__lt__()不存在则报错
         <: 规则和大于相反
         >=:首先找__ge__(), 没有找__le__()
            并将执行__le__()结果取反
            __le__()不存在则报错
         <=:规则和大于等于相反
         ==:首先找__eq__(), 如果不能存在则
            判断两个对象ID值,相同返回True
            不同返回False
         !=:首先找__ne__(),不存在则找
            __eq__()并执行取反
            如果__eq__()不存在则比较ID
            ID相同返回False,否则返回True
     
     课堂练习:在MyList类中,重载>,<,==,!=
       操作符,比较规则如下:
       等于:data属性元素个数相等
             并且相同位置上的值相等
       大小比较:[1,2,4] > [1,2,3]
                 [1,2,3,4] > [1,2,3]
                 [1,2,4] > [1,2,3,4]
       代码见:mylist.py   
      
     7)一元运算符:带一个操作数的操作符
       __neg__(self)   -self  负号运算
       __pos__(self)   +self  正号运算
       __invert__(self) ~self 取反运算

      
       作用:重写上述方法,支持对象如下操作:
             -obj, +obj, ~obj
            
     8)in/not in运算符重载
        只需要重载__contains__(self,e)
        in运算,则直接调用__contains__()
        not in运算,调用__contains__()取反

    
     9)索引运算符重载:支持[]操作
        __getitem__(self,i)       self[i]
        __setitem__(self,i,value) self[i]=value
        __delitem__(self,i)       del self[i]

3. 实例的内置属性
   1)__dict__属性:绑定实例自身的变量字典
      包括父类创建的属性和私有属性

      示例:
      am = AutoMobile("卡车","blue",4.0)
      print(am.__dict__)

     
  2)__class__属性:绑定创建该对象的类
     
作业:   
1)编写一个汽车租赁程序,包含汽车类(Car),
客户类(Customer), 租车店类(CarStore),各个
类包含的属性和方法有:
     Car类:
         属性
         car_id    车辆id号
         name    车辆名称
         is_lend    是否出租
         price    每天单价
         start_date    起租日期
         end_date    租赁终止日期
         方法
         __str__()
        
     Customer类:
         属性
         cust_id        客户编号
         cust_name    客户姓名
         tel_no        客户电话
         方法
         __str__()
     CarStore类:
         属性
         cars        所有车辆列表
         customers    所有客户列表
         方法
         __load_cars()    加载所有车辆信息
         __load_customers()    加载所有客户信息
         print_cars_info()    打印所有车辆信息
         find_car()            查找车辆
         add_car()            添加车辆
         del_car()            删除汽车
         lend()                租车
         back()                还车
2)实现上述类,并编写测试代码
    

PYTHON1.面向对象_day03
  1 # car_store.py
  2 # 汽车租赁模拟程序
  3 class Car: # 车辆类
  4     def __init__(self, car_id, name,
  5                  price, is_lend):
  6         self.car_id = car_id #车辆编号
  7         self.name = name #名称
  8         self.price = price #价格
  9         self.is_lend = is_lend #是否出租
 10         self.start_date = "" #起租日期
 11         self.end_date = "" #预计归还日期
 12         self.cust_id = "" #租车客户编号
 13 
 14     def __str__(self):
 15         ret = "车辆编号:%s,名称:%s,单价:%.2f," \
 16             "是否出租:%s" %(self.car_id,
 17             self.name, self.price,self.is_lend)
 18         return ret
 19 
 20 class Customer: #客户类
 21     def __init__(self,cust_id,cust_name,tel_no):
 22         self.cust_id = cust_id
 23         self.cust_name = cust_name
 24         self.tel_no = tel_no
 25 
 26     def __str__(self):
 27         ret = "客户编号:%s,客户名称:%s,电话:%s" \
 28           %(self.cust_id, self.cust_name, self.tel_no)
 29 
 30 class CarStore: #租车店类
 31     def __init__(self):
 32         self.cars = [] #车辆列表
 33         self.customers = [] #客户列表
 34         self.__load_cars() #加载车辆列表
 35         self.__load_customers()#加载客户列表
 36 
 37     def __load_cars(self): #加载车辆列表
 38         self.cars.append(Car("1","GOLF",400,"否"))
 39         self.cars.append(Car("2","凯越",350,"否"))
 40         self.cars.append(Car("3","奥迪",1200,"否"))
 41         self.cars.append(Car("4","凯美瑞",800,"否"))
 42         self.cars.append(Car("5","宝来",450,"否"))
 43 
 44     def __load_cars(self): #加载车辆列表,从文件中读取
 45         with open("/home/tarena/aid1805/lx/面向对象/day03/cars_list.txt") as f:
 46             line = f.readline(256).replace("\n","")
 47             custinfo = line.split(",")
 48             car_id = custinfo[0]
 49             car_name = custinfo[1]
 50             price = float(custinfo[2])
 51             is_len = custinfo[3]
 52             car = Car(car_id,car_name,price,is_len)
 53             self.cars.append(car) #对象添加到列表
 54 
 55     def __load_customers(self):#加载客户列表
 56         cust1 = Customer("C0001","张大大","15811223344")
 57         cust2 = Customer("C0002","李小小","13233333444")
 58         cust3 = Customer("C0003","赵四","18044445555")
 59         self.customers.append(cust1)
 60         self.customers.append(cust2)
 61         self.customers.append(cust3)
 62 
 63     def print_cars_info(self): #打印车辆信息
 64         for car in self.cars: #遍历车辆列表并打印
 65             print(car)
 66 
 67     def find_car(self, car_id): #根据车辆编号查询
 68         for car in self.cars: #遍历车辆列表
 69             if car.car_id == car_id: #编号相等
 70                 print(car)
 71                 return
 72         print("未找到车辆信息")
 73         return
 74 
 75     def add_car(self, car): #添加车辆,car为Car的对象
 76         if isinstance(car, Car): #car是Car类的实例
 77             self.cars.append(car)
 78         else:
 79             print("对象类型有误")
 80         #可以增加id号是否存在的逻辑判断
 81         return
 82 
 83     def del_car(self, car_id): #根据车辆编号删除
 84         for car in self.cars:
 85             if car.car_id == car_id:
 86                 self.cars.remove(car) #删除对象
 87         return
 88 
 89     def lend(self, car_id, cust_id,
 90             start_date, end_date): #租车
 91         for car in self.cars:
 92             if car.car_id == car_id:
 93                 if car.is_lend == "是":#已出租
 94                     print("该车辆已经出租")
 95                     return
 96                 else: #未出租
 97                     setattr(car, "is_lend", "是")#改状态
 98                     setattr(car, "cust_id", cust_id)
 99                     setattr(car, "start_date", start_date)
100                     setattr(car, "end_date", end_date)
101                     print("车辆出租登记完成")
102                     return
103         print("未找到车辆信息")
104         return
105 
106     def back(self, car_id): #还车
107         for car in self.cars:
108             if car.car_id == car_id:
109                 setattr(car, "is_lend", "否")#改状态
110                 setattr(car, "cust_id", "")
111                 setattr(car, "start_date", "")
112                 setattr(car, "end_date", "")
113                 print("还车登记完成")
114                 return
115         print("未找到该车辆信息")
116         return
117 
118 if __name__ == "__main__":
119     car_store = CarStore()  #实例化租车店对象
120     car_store.print_cars_info() #打印车辆信息
121     print("")
122     #租车方法测试
123     car_store.lend("3","C0001","2018-01-01","2018-01-03")
124     car_store.print_cars_info()
125 
126     #还车方法测试
127     car_store.back("3")
128     car_store.print_cars_info()
129 
130      #添加车辆方法测试
131     car_store.find_car("3") #查找编号为3的车辆
132 
133     car = Car("6","捷达",300,"否")
134     car_store.add_car(car)  #将car对象添加到cars列表
135     car_store.print_cars_info()
car_store.pyPYTHON1.面向对象_day03

上一篇:07JavaScript数据类型


下一篇:开源的连接池技术DBCP和C3P0