封装、继承、多态

发布时间 2024-01-04 16:31:01作者: Formerly0^0

封装、继承、多态

1.封装

  • 封装就是将属性隐藏,不让外界发现或使用
  • 将可以允许外界使用的内容通过接口开发,让用户通过接口使用
  • 隐藏属性的方法是通过 __变量名

1.1封装之隐藏属性

  • 隐藏数据属性
class Teacher:
    def __init__(self, name, age):
        # 将名字和年纪都隐藏起来
        self.__name = name
        self.__age = age

    # 对外提供访问老师信息的接口
    def tell_info(self):
        print('姓名:%s,年龄:%s' % (self.__name, self.__age))

    # 对外提供设置老师信息的接口,并附加类型检查的逻辑
    def set_info(self, name, age):
        if not isinstance(name, str):
            raise TypeError('姓名必须是字符串类型')
        if not isinstance(age, int):
            raise TypeError('年龄必须是整型')
        self.__name = name
        self.__age = age


# 实例化类得到对象
teacher = Teacher("serein", 18)
# 查看对象的信息
teacher.tell_info() # 姓名:serein,年龄:18

# 调用对象的方法修改对象的信息 , 符合要求就能修改成功
teacher.set_info('formerly', 22)

# 查看对象的信息
teacher.tell_info() # 姓名:formerly,年龄:22
  • 隐藏函数属性
class ATM:
    # 插卡
    def __card(self):
        print('插卡')

    # 身份认证
    def __auth(self):
        print('用户认证')

    # 输入金额
    def __input(self):
        print('输入取款金额')

    # 打印小票
    def __print_bill(self):
        print('打印账单')

    # 取钱
    def __take_money(self):
        print('取款')

    # 取款功能
    def withdraw(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__print_bill()
        self.__take_money()


obj = ATM()
obj.withdraw()
# 插卡
# 用户认证
# 输入取款金额
# 打印账单
# 取款

1.2 property装饰器

class Foo:
    def __init__(self, val):
        # 将属性隐藏
        self.__NAME = val

    @property
    def name(self):
        print(f'我在获取的时候被触发了')
        return self.__NAME

    @name.setter  # 设置值
    def name(self, value):
        print(f'我再修改的时候被触发了')
        # 在设定值之前进行类型检查
        if not isinstance(value, str):
            raise TypeError('%s must be str' % value)
        # 通过类型检查后,将值value存放到真实的位置self.__NAME
        self.__NAME = value

    @name.deleter  # 删除值
    def name(self):
        print(f'删除的时候调用了我')
        raise PermissionError('Can not delete')


f = Foo('serein')
# print(f.name)

# 触发name.setter装饰器对应的函数name(f,'formerly')
f.name = 'formerly'
print(f.name)
# 触发name.setter对应的的函数name(f,123),抛出异常TypeError
f.name = 123

# 触发name.deleter对应的函数name(f),抛出异常PermissionError
del f.name

2.继承

  • 子类可以继承父类中的方法和类变量(不是拷贝一份,父类的还是属于父类,子类可以继承而已)
  • 父类也可以叫基类,子类也可以叫派生类
class Base:

    def func(self):
        print("Base.func")

class Son(Base):
    
    def show(self):
        print("Son.show")
        
s1 = Son()
s1.show() # Son.show
s1.func() # 优先在自己的类中找,自己没有才去父类。
# Base.func

2.1 属性查找顺序

class Base:
    def f1(self):
        print('before')
        self.f2() # slef是obj对象(Foo类创建的对象) obj.f2
        print('base.f1')
        
	def f2(self):
        print('base.f2')
        
class Foo(Base):
    def f2(self):
        print('foo.f2')
        
obj = Foo()
obj.f1() # 优先去Foo类中找f1,因为调用f1的那个对象是Foo类创建出来的。


>>> before
>>> foo.f2
>>> base.f1

b1 = Base()
b1.f1()

>>> before
>>> base.f2
>>> base.f1

查找总结

  • 执行对象.方法时,优先去当前对象所关联的类中找,没有的话才去她的父类中查找。
  • Python支持多继承:先继承左边、再继承右边的。
  • self到底是谁?去self对应的那个类中去获取成员,没有就按照继承关系向上查找 。

2.2 隐藏属性

class Foo:
    # 变形为_Foo__fa
    def __f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        # 变形为self._Foo__fa,因而只会调用自己所在的类中的方法
        # _Foo__f1
        self.__f1()
        #
        self._Bar__f1()


class Bar(Foo):
    # 变形为_Bar__f1
    def __f1(self):
        print('Bar.f1')

# _Bar__f1
b = Bar()
# 在父类中找到f2方法,进而调用b._Foo__f1()方法,同样是在父类中找到该方法
b.f2()

# 隐藏属性 : 隐藏给当前类,除了当前类,其他继承的子类均不能找到我隐藏的属性