Python编程学习-基础笔记07

九、面向对象编程

9.1 私有化

'''
私有化:
    封装: 1,私有化属性;2,定义共有的set和get方法
    __属性 : 就是将属性私有化,将访问范围控制在类中
    优点:
        1,隐藏属性,不被外界随意修改
        2,可以通过函数set来修改
            def setXXX(self,xxx)
        3,筛选赋值内容,加if判断
        4,如果想获取具体的某一属性,使用get函数
            def getXXX(self)
'''
class Student:
    def __init__(self,name,age):
        self.__name = name
        self.__age = age
        self.__score = 59

    #定义共有的set和get方法
    #set 是赋值
    def setAge(self,age):
        if age > 0 and age < 100:
            self.__age = age
        else:
            print('年龄不在规定的范围')

    def setName(self,name):
        if len(name)==6:
            self.__name = name
        else:
            print('姓名不是6位!')
    #get 是取值
    def getAge(self):
        return self.__age
    def __str__(self):
        return f'姓名:{self.__name},年龄:{self.__age},分数:{self.__score}'

jack = Student('Jack',19)
print(jack)
jack.setAge(100) # 超出范围,年龄不在规定的范围
print(jack) #姓名:Jack,年龄:19,分数:59  依然打印原始值
print(jack.getAge())

9.2 @property装饰器

'''
在开发中常看到的一些私有化处理:装饰器
'''
class Student:
    def __init__(self,name,age):
        self.name = name
        self.__age = age

    #旧版
    # #set 是赋值
    # def setAge(self,age):
    #     if age > 0 and age < 100:
    #         self.__age = age
    #     else:
    #         print('年龄不在规定的范围')
    # #get 是取值
    # def getAge(self):
    #     return self.__age
    #新版,加装饰器,先有getxxx
    @property
    def age(self):
        return self.__age
    #必须首先定义age函数,再定义setXXX
    @age.setter
    def age(self,age):
        if age > 0 and age < 100:
            self.__age = age
        else:
            print('年龄不在规定的范围')


    def __str__(self):
        return f'姓名:{self.name},年龄:{self.__age}'

s = Student('Jack',19)
print(s)
#name 没有私有化
s.name = 'Luise'
print(s)
# #旧版:私有化赋值
# s.setAge(30)
# print(s.getAge())
#新版加装饰器的赋值
s.age = 100
print(s.age)

9.3 关联关系

'''
关联: has a; 继承: is a
练习要求:
公路 Road
    属性:公路名称,公路长度
车 Car
    属性:车名,时速
    方法:
        1,求车在哪条公路上以多少时速行驶了多长距离
            get_time(self,road)
        2,初始化车属性信息 __init__方法
        3,打印对象,现实车的属性信息
'''
import random

#定义road 类
class Road:
    def __init__(self,name,length):
        self.name = name
        self.length = length
    def __str__(self):
        return  f'公路名:{self.name},长度:{self.length}'
#定义car类
class Car:
    def __init__(self,brand,speed):
        self.brand = brand
        self.speed = speed

    def get_time(self,road): # road = r ,他们指向同一地址
        ran_time = random.randint(1,10)
        msg = f'{self.brand}的车在{road.name}高速上以{self.speed}km/h行驶了{ran_time}小时'
        return msg
    def __str__(self):
        return  f'品牌:{self.brand},速度:{self.speed}'
#创建实例对象
r = Road('S51',500)
print(r) #公路名:S51,长度:500
audi = Car('Audi',120)
print(audi) #品牌:Audi,速度:120
print(audi.get_time(r)) #Audi的车在S51高速上以120km/h行驶了3小时
r.name = 'S35'
print(audi.get_time(r)) #Audi的车在S35高速上以120km/h行驶了5小时

对象也是一种数据类型。

'''
关联: has a
    1,has a
        一个类中使用了另一个自定义的类型
        student 使用了computer 和 book
    2,类型:
        系统类型: str,list,dict .....
        自定义类型:算是自定义的类,都可以当成一种类型
            s = Student()
            s是Student类型的对象
'''
# student computer book 3类
class Computer:
    def __init__(self,brand,type,color):
        self.brand = brand
        self.type = type
        self.color = color

    def online(self):
        print('Connect to internet')

    def __str__(self):
        return self.brand + '---' + self.type + '---' + self.color

class Book:
    def __init__(self,bname,author,number):
        self.bname = bname
        self.author = author
        self.number = number

    def __str__(self):
        return self.bname + '---' + self.author + '---' + str(self.number)

class Student: #has a
    def __init__(self,name,computer,book):
        self.name = name
        self.computer = computer
        self.books = []
        self.books.append(book)
	#借书
    def borrow_book(self,book):
        for book1 in self.books:
            if book1.bname == book.bname:
                print('此书已经借阅过')
                break
        else:
            self.books.append(book)
            print(f'{book},添加成功')

    def show_book(self):
        for book in self.books:
            print(book.bname)

    def __str__(self):
        return self.name + '---/' + str(self.computer) + '---/' + str(self.books)
#创建对象
computer = Computer('Huawei','MacBook','Black')
book = Book('三体','刘慈欣',3)
stu = Student('Jack',computer,book)
print(stu)
stu.show_book()
stu.borrow_book(book)
print('******************************')
book1 = Book('独臂刀客','古龙',10)
stu.borrow_book(book1)
print('------------------------')
stu.show_book()
print('******************************')
book2 = Book('流浪地球','刘慈欣',3)
stu.borrow_book(book2)
print('------------------------')
stu.show_book()

9.4 继承关系

9.4.1 父类和子类都不带任何参数的情况

'''
继承: is a   base class, 也称为父类或基类
    Student,Employee, Doctor --> 都属于人类
    相同的代码 --》 冗余代码,可读性不高
    将相同的代码提取 --》 Person 类
        Student,Employee, Doctor --> 继承父类Person
        class Student(Person):
            pass

'''
# student Employee Doctor 3类 父类 Person
#定义父类Person
class Person:
    def __init__(self):
        self.name = 'Forrest'
        self.age = 18

    def eat(self):
        print(f'{self.name} like to eat FISH')

#继承父类Person
class Student(Person):
    pass
#继承父类Person
class Employee(Person):
    pass
#继承父类Person
class Doctor(Person):
    pass

s = Student()
s.eat()

9.4.2 带参数的情况

'''
继承: is a   base class, 也称为父类或基类
    Student,Employee, Doctor --> 都属于人类
    相同的代码 --》 冗余代码,可读性不高
    将相同的代码提取 --》 Person 类
        Student,Employee, Doctor --> 继承父类Person
        class Student(Person):
            pass
特点:
    1,如果类中不定义__init__,调用父类super class 中的__init__
    2,如果类继承了父类,也定义了自己的__init__,就需要在当前类中去调用父类__init__
    3,如果调用父类__init__:
        super().__init__([参数])
        super(类名,对象).__init__([参数])
    4,如果父类有eat,子类也有eat方法,搜素的原则是先找当前类,当前类没有的话,再去找父类
        s.eat()
        override:重写(覆盖) --》 父类的方法无法满足子类的需求,就需要在子类定义个重名的方法
    5,子类的方法中可以去调用父类的方法
        super().方法名(参数)
'''
# student Employee Doctor 3类 父类 Person
#定义父类Person
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def eat(self,food):
        print(f'{self.name} like to eat {food}')

#继承父类Person
class Student(Person):
    def __init__(self,name,age,clazz):
        print('子类的init')
        #将参数传给父类的__init__
        super().__init__(name,age) #super() 父类对象
        #子类特有的部分
        self.clazz = clazz
    #override:重写
    def eat(self,food,fruit):
        #调用父类的方法
        super(Student, self).eat(food)
        #增加子类的需求
        print(f'{self.name} also like to eat {fruit}')
#继承父类Person
class Employee(Person):
    def __init__(self,name,age,salary,joblevel):
        print('子类的init')
        #将参数传给父类的__init__
        super().__init__(name,age) #super() 父类对象
        # 子类特有的部分
        self.salary = salary
        self.joblevel = joblevel
#继承父类Person
class Doctor(Person):
    def __init__(self,name,age,patients):
        print('子类的init')
        #将参数传给父类的__init__, 加判断super(Doctor,self),等同于super()
        super(Doctor,self).__init__(name,age) #super() 父类对象
        # 子类特有的部分
        self.patients = patients

s = Student('Jack',18,'高三一班')
s.eat('Fish','Peach')
e = Employee('Forrest',25,50000,'Ariel')
e.eat('Apple')
lists = ['Je','King','Ice','Jason']
d = Doctor('Ferry',50,lists)
d.eat('Banana')

9.5 案例

'''
编写工资管理程序:
    1,系统可以管理以下四类人:
        工人 worker
        销售 salesman
        经理 manager
        销售经理 sales manager
    2,所有员工都具有工号、姓名、工资等属性,有设置姓名、获取姓名、获取员工号、计算工资等方法
        1)工人: 具有工作小时数和时薪的属性,工资计算方法为 工作小时数 * 时薪
        2)销售:具有销售额和提成比例的属性,工资计算方法为 销售额 * 提成比例
        3)经理:具有固定月薪属性,工资计算方法为 固定月薪
        4)销售经理:工资计算方法为 销售额 * 提成比例 + 固定月薪
根据以上需求,完成以下功能:
    1,添加所有类型的人员
    2,计算月薪
    3,显示所有人员的工资情况
'''
#父类
class Employee:
    def __init__(self,name,eid,salary):
        self.__name = name
        self.__eid = eid
        self.salary = salary

    def getSalary(self):
        return self.salary

    def __str__(self):
        return f'工号:{self.__eid},姓名:{self.__name},本月工资是:{self.salary}'

#worker类
class Worker(Employee):
    def __init__(self,name,eid,salary,hours,hourly_rate):
        super(Worker, self).__init__(name,eid,salary)
        self.hours = hours
        self.hourly_rate = hourly_rate

    def getSalary(self):
        money = self.hours * self.hourly_rate
        self.salary += money
        return self.salary

#销售类
class Salesman(Employee):
    def __init__(self,name,eid,salary,sales_amount, percentage):
        super(Salesman, self).__init__(name,eid,salary)
        self.sales_amount = sales_amount
        self.percentage = percentage

    def getSalary(self):
        money = self.sales_amount * self.percentage
        self.salary += money
        return self.salary
#经理类
class Manager(Employee):
    def __init__(self, name, eid, salary):
        super().__init__(name, eid, salary)

    def getSalary(self):
        super(Manager, self).getSalary()

#销售经理类
class Salesmanager(Employee):
    def __init__(self, name, eid, salary,total_amount, percentage):
        super().__init__(name, eid, salary)
        self.total_amount = total_amount
        self.percentage = percentage

    def getSalary(self):
        money = self.total_amount * self.percentage
        self.salary += money
        return self.salary
#创建对象
w = Worker('Forrest',10001, 50000,160,25)
salary = w.getSalary()
print(w)
print('-----------')
s = Salesman('Jack',10002,2000,1000000,0.003)
s.getSalary()
print(s)
print('-----------')
m = Manager('Jessie',10003,20000)
m.getSalary()
print(m)

print('-----------')
sm = Salesmanager('Jack',10004,5000,10000000,0.003)
sm.getSalary()
print(sm)

9.6 多重继承与MRO

'''
多继承与mro:
    python运行多继承
    def 子类(父类1,父类2,……):
        pass
    如果父类中有相同名称的方法,搜索顺序:
        python2 深度优先  python3 广度优先
        python2 : D -->C1-->P1-->P2-->object-->C2
        python3 : D -->C1 -->C2 --> P1 -->P2 --> object 
    mro :python 查看调用顺序的内置函数
'''
#经典类
class P1:
    def foo(self):
        print('P1--->foo')

class P2:
    def foo(self):
        print('P2--->foo')

    def bar(self):
        print('P2--->bar')

class C1(P1,P2):
    pass

class C2(P1,P2):
    def bar(self):
        print('C2--->bar')

class D(C1,C2):
    pass

import inspect
#创建对象
d = D()
#打印搜索顺序
print(D.__mro__) #(<class '__main__.D'>, <class '__main__.C1'>, <class '__main__.C2'>, <class '__main__.P1'>, <class '__main__.P2'>, <class 'object'>)
print(inspect.getmro(D))
d.foo()
d.bar()

#新式类,定义class P1(object): #加上默认的继承

调用顺序如下:

9.7 多态

'''
多态:
pet 父类      cat dog 子类
per 大类型     cat dog 小类型
'''
class Person:
    def __init__(self,name):
        self.name = name

    def raise_pet(self,pet):
        #判断是否是宠物类
        #isinstance(obj, 类) --》 判断obj是不是这个类的对象,或者判断obj是该类子类的对象
        if isinstance(pet, Pet): #pet 既可以接收cat,dog,也可以接收tiger
            print(f'{self.name}喜欢养宠物,昵称是:{pet.nickname}')
        else:
            print('不是宠物,千万别养……')

class Pet:
    def __init__(self,nickname,age):
        self.nickname = nickname
        self.age = age

    def show(self):
        print(f'昵称:{self.nickname},年龄:{self.age}')

class Cat(Pet):
    role = '猫'
    def catch_mouse(self):
        print('抓老鼠……')

class Dog(Pet):
    role = '狗'
    def watch_gate(self):
        print('看门狗……')

class Tiger:
    print('老虎不是宠物')
#创建对象
cat = Cat('咪咪',3)
dog = Dog('大黄',2)
tiger = Tiger()
person = Person('Jack')

person.raise_pet(cat)
print('---------')
person.raise_pet(tiger)
posted @ 2022-07-14 14:40  逆流的鱼2016  阅读(33)  评论(0编辑  收藏  举报