python(12)面向对象 封装、继承、多态

一、封装

私有化
封装:
1、私有化属性
2、定义公有的set和get方法

__属性:将属性私有化,访问范围仅仅限于类中

优点:
1、隐藏属性,不被外界随意修改
2、也可以修改,通过函数
def setXXX(self, xxx):
    3、筛选赋值的内容
    if xxx是否符合条件:
        赋值
    else:
        不赋值
4、如果想获取具体的某一个属性
使用get函数
def getXXX(self):
    return self.__xxx


attribute setName getName setAge getAge

在开发中,看到一些私有化处理:装饰器
class Student:
    # __age = 18  #类属性

    def __init__(self, name, age):
        self.name = name
        self.__age = age
        self.__score = 59

    def __str__(self):
        return '姓名{},年龄{},考试分数{}'.format(self.name, self.__age, self.__score)

    #旧版set、get方法
    #定义公有的set和get方法
    #set是为了赋值
    # def setAge(self, age):
    #     if age > 0 and age < 120:
    #         self.__age = age
    #     else:
    #         print("年龄不在规定范围内")

    # #get是为了取值
    # def getAge(self):
    #     return self.__age

    #新版
    #先定义get的xxx,再有xxx.set,因为set依赖get
    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        if age > 0 and age < 100:
            self.__age = age
        else:
            print("年龄赋值错误")

#旧版
s = Student('name1', 18)
print(s)
# s.setAge(20)
# print(s)

print(dir(Student)) #获取类中所有属性
print(s.__dir__())  #获取类中所有属性,包括私有
print(s._Student__age)  #系统自动将私有属性改名, _Student__age其实就是__age
print(__name__)

print("*" * 80)


#新版
s1 = Student('name333', 15)
print(s1.name)
#私有化的赋值
# s1.setAge(30)
# print(s1.getAge())

print(s1.age)

 

二、继承

继承: is a, has a
例如:
公路(Road) 属性:公路名称、公路长度

车(Car) 属性:车名、时速
方法:
1、求车名在那条公路上以多少的时速行驶了多长get_time(self, road)
2、初始化车属性信息 __init__方法
3、打印对象显示车的属性信息

1、has a  包含, 类中有...
1)、一个类中使用了另外一种自定义的类型
2)、类型:
系统类型:
str int float
list dic tuple set
自定义类型:
自定义的类,都可以将其当成一种类型
s = Student()
s是Student类型的对象
import random
class Road:
    def __init__(self, name, len):
        self.name = name
        self.len = len

class Car:
    def __init__(self, road, brand, speed):
        self.road = road
        self.brand = brand
        self.speed = speed

    def get_time(self):   #road 与 r指向同一个地址空间
        ran_time = random.randint(1, 10)
        msg = '{}品牌的车在{}上,以{}的时速行驶{}时间'.format(self.brand, self.road.name, self.speed, ran_time)
        print(msg)

    def __str__(self):
        return '{}品牌的,速度{}'.format(self.brand, self.speed)

#创建实例化对象
r = Road("青藏公路", 12000)
c = Car(r, "奥迪", 120)  #此处  Car类中使用了另一个自定义类Road 为 has a

print(c)
c.get_time()

 

2、is a   base class 基类 父类
父类  子类
ValueError Exception BaseException

Student, Employee, Doctor  都属于人类
相同代码--->代码冗余,可读性不高

将相同代码提取--->Person类
Student, Employee, Doctor  继承 Person
父类
class Person:
    pass

子类
class Student(Person):
    pass

特点:
1、如果类中不定义__init__,默认调用父类 super class的__init__
2、如果类继承父类,也需要定义自己的__init__,就需要在子类__init__中
调用父类的__init__
3、如何调用父类__init__:
    super().__init__(参数)
    super(类名, self).__init__(参数)
4、如果父类有eat(),子类也定义一个eat()方法,搜索的原则:
先找当前类,没有再去找父类
override 重写(覆盖)
父类提供的方法,不能满足子类的需求,就需要在子类中定义一个同名的方法,
这种行为为:重写
5、子类的方法中,也可以调用父类的方法
    super().方法名(参数)
#将每个类共同的属性和方法提取出来
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = 20
        print("------> Person的init")
    
    def run(self):
        print("{}正在跑步".format(self.name))

    def eat(self):
        print("{}正在吃饭".format(self.name))

class Student(Person):
    def __init__(self, name, age, clazz):
        print('--->Student的init')
        #如何调用父类__init__     super() 父类对象
        super().__init__(name, age)
        self.clazz = clazz

    def study(self, course):
        print("{}正在学习{}课程".format(self.name, course))

    #子类中与父类同名的方法,直接调用自己的方法,优先找自己的方法,不去找父类的方法
    def eat(self, food):
        super().eat()  #先调用父类的代码
        print("{}正在吃饭,喜欢吃{}".format(self.name, food))

class Employee(Person):
    def __init__(self, name, age, salary, manager):
        super().__init__(name, age)
        self.salary = salary
        self.manager = manager

class Doctor(Person):
    def __init__(self, name, age, patient):
        super(Doctor, self).__init__(name, age)
        self.patient = patient

s = Student("stu", 20, "一年级")
s.run()
s.study('python')
s.eat('满汉全席')
e = Employee('ee', 40, 10000, 'king')
e.run()
list1 = ['aaa', 'bbb', 'ccc']
d = Doctor('d', 40, list1)
d.run()

 

3、多继承
python允许多继承
def 子类(父类1, 父类2, ...)

类名.__mro__    输出搜索顺序
import inspect
inspect.getmro(类名)

如果父类中有相同名称的方法,搜索顺序  经典类  新式类

python2.7 -- 从左至右,深度优先  一个父类搜索完再搜索其它的父类

python3 -- 广度优先   现在执行的环境   子类所有父类,其中一个父类所有父类...
class Base:
    def test(self):
        print("-------Base---------")

class A(Base):
    def test(self):
        print("--->AAAAAAA")

class B(Base):
    def test(self):
        print("--->BBBBBB")

class C(Base):
    def test(self):
        print("------>CCCCCC")

class D(A, B, C):
    pass

c = C()
c.test()  #输出:------>CCCCCC
d = D()
d.test()
print(D.__mro__)  #查看搜索顺序

import inspect
print(inspect.getmro(D))  #查看继承搜索顺序

 

三、多态

class Person:
    def __init__(self, name):
        self.name = name

    def feed_pet(self, pet):  #既可以接收cat,也可以接收dog,还可以接受tiger
        # isinistance(obj, 类)  --->验证obj是不是类的对象,或者判断obj是不是该类子类的对象
        if isinstance(pet, Pet):
            print("{}喜欢养宠物:{},暱称是{}".format(self.name,pet.role, pet.nickname))
        else:
            print("不是宠物")

#宠物
class Pet:
    role = "宠物"
    def __init__(self, nickname, age):
        self.nickname = nickname
        self.age = age

    def show(self):
        print("暱称是:{}, 年龄:{}".format(self.nickname, self.age))

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

class Dog(Pet):
    role = "狗"
    def watch_house(self):
        print("看门")

class Tiger:
    def eat(self):
        print("吃人")

#创建对象
cat = Cat('小猫', 2)
dog = Dog('小狗', 3)
tiger = Tiger()

p = Person('人')
p.feed_pet(cat)

p.feed_pet(tiger)
Pet
pet 父类   cat dog 子类
pet 大类型 cat dog 小类型

 

四、总结

面向对象的特点:
封装、继承、多态
1、封装:
私有化属性,定义公有set和get方法
class Student:
    def __init__(self, age):
        self.__age = age

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age)
        self.__age = age

s = Student()
s.age = 10


继承:
父类中的私有属性,子类无法继承
is a:
父类(提取出来的共同的特征) 子类
class Student(Person):
    pass

has a:
class Student:
    def __init__(self, 参数)
        参数是自定义类型

s = Student()

多继承:
class C(A, B):
    pass

C.__mro__  查看搜索顺序


多态:  
class Person:
    def feed_pet(self, pet)  #只要是pet的子类,都可以
        if isinstance(pet, Pet):
            pass
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章