20.面向对象【四】

【一】抽象类

抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

# 所有继承父类的子类必须重写父类的某些方法,这个父类就叫抽象类
import abc
class Animal(metaclass=abc.ABCMeta):
    def __init__(self, color, foot):
        self.color = color
        self.foot = foot
    def tell(self):
        print(f"The color of this animal is {self.color}")
    # 在子类中必须重写当前的方法
    @abc.abstractmethod
    def speak(self):
        print(f'动物叫声')
class Cat(Animal):
    def __init__(self, color, foot):
        super().__init__(color, foot)
    # 如果不重写父类的方法会报错
    def speak(self):
        print('喵喵叫')
cat1 = Cat('black', '4')
cat1.tell()
# The color of this animal is black
cat1.speak()
# 喵喵叫

【二】多态与多态性

1)多态

  • 指的是一类事件有多种形态(动物:猫狗...)

2)多态性

  • 多态动态绑定在继承的背景下使用时,称为多态性

  • 多态性指在不考虑实例类型的情况下使用实例

  • 多态性在面向对象方法的表述

    • 向不同对象发同一个消息,不同的对象会产生不同的行为
    • 即每个对象可以用自己的方法去响应同种消息

3)多态性的分类

1.静态多态性

运算+表达式

2.动态多态性

import abc
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def speak(self):
        print(f'动物叫声')
class Dog(Animal):
    def speak(self):
        print('汪汪叫')
class Cat(Animal):
    def speak(self):
        print('喵喵叫')
# 定义统一接口
def speak(obj):
    obj.speak()
dog = Dog()
cat = Cat()
speak(dog)
# 汪汪叫
speak(cat)
# 喵喵叫

4)多态性的好处

  • 增加了程序的灵活性
  • 增加了程序的可扩展性

5)鸭子类型(duck typing)

  • 是一种编程风格,决定一个对象是否有正确的接口

  • 通过强调接口而不是特定类型,设计良好的代码通过多态提高了灵活性

  • 强制重写父类方法:抽象类

    • 不依赖于继承,只需要制造出外观和行为相同对象

    • 不考虑对象类型而使用对象,

【三】绑定方法与非绑定方法

1)绑定到对象的方法

  • 没有装饰器的方法
class Student(object):
    def __init__(self, name):
        self.name = name
    def talk(self):
        print(f'Hello {self.name}')
st1 = Student('diva')
# 对象可直接调用绑定给对象的方法
st1.talk()  # Hello diva
# 类调用绑定给对象的方法,需主动传入一个生成的对象
Student.talk(st1)  # Hello diva

2)绑定给类的方法

  • 用classmethod装饰器装饰的方法。
class Student(object):
    def __init__(self, name):
        self.name = name
    @classmethod
    def talk(cls, name):
        obj = cls(name)
        print(f'Hello {obj.name}')
print(Student.talk)  
# <bound method Student.talk of <class '__main__.Student'>>
st1 = Student('diva')
# 对象调用绑定给类的方法, 默认将实例化得到当前对象的类自动传入
st1.talk('diva')  # Hello diva
# 类调用绑定给类的方法,类可以直接调用,默认将调用当前方法的类自动传入
Student.talk('diva')  # Hello diva

3)非绑定方法

  • 用staticmethod装饰器装饰的方法
  • 不与类或对象绑定,类和对象都可以调用,但是没不会自动传值
class Student(object):
    def __init__(self, name):
        self.name = name
    @staticmethod
    def talk():
        print("Hello")
st1 = Student("diva")
# 对象调用非绑定方法, 不用传任何参数,和普通函数一样
st1.talk()  # Hello
# 类调用非绑定方法, 不用传任何参数,和普通函数一样
Student.talk()  # Hello

【四】反射

  • 反射是一种程序可以访问、检测和修改其本身状态或行为的方式
  • 在Python中,反射主要指通过字符串映射自己的内部是否具有某种属性
class Student(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def tell(self):
        print(f"{self.name} is {self.age} years old")
    @classmethod
    def talk_c(cls, name):
        obj = cls(name)
        print(f'Hello {obj.name}')
    @staticmethod
    def talk_s():
        print("Hello")
st1 = Student('diva', 20)

1)getattr(obj,key)

  • 获取对象的属性值,如果属性不存在,可提供默认值
# 数据属性:在对象中映射数据属性时,如果对象中存在当前属性值则直接将属性值拿出
result = getattr(st1, 'name')
print(result)  # diva

# 函数属性:如果存在则直接获取当前函数属性的内存地址,可直接调用
result = getattr(st1, 'tell')
print(result)
# <bound method Student.tell of <__main__.Student object at 0x000002613E7CD0D0>>
result()
# diva is 20 years old

# 不存在:会直接报错

2)hasattr(obj,key)

  • 判断对象是否具有指定属性
# 数据属性:在对象中映射数据属性时,如果对象中存在当前属性值,则返回True
result = hasattr(st1, 'name')
print(result)  # True

# 函数属性:如果对象中存在当前属性名对应的数据属性,则返回True
result = hasattr(st1, 'tell')
print(result)  # True

# 不存在:返回False

3)setattr(obj,key,value)

  • 设置对象的属性值
# 数据属性:向对象设置属性名和属性值时,存在则替换,不存在则新增
result = setattr(st1, 'name', 'a')
print(result)  # None
print(st1.name)  # a
result = setattr(st1, 'sex', 'man')
print(result)  # None
print(st1.sex)  # man

# 函数属性:如果对象中存在当前属性名对应的数据属性,则返回True
def read():
    print(f'读')
result = setattr(st1, 'read', read)
print(result)  # None
print(hasattr(st1, 'read'))  # True
print(getattr(st1, 'read'))  # <function read at 0x000002089A6E04A0>
getattr(st1, 'read')()  # 读
st1.read()  # 读

4)delattr(obj,key)

  • 删除对象属性
# 数据属性:在对象删除时,如果对象中存在则直接删除
print(hasattr(st1, 'name'))  # True
result = delattr(st1, 'name')
print(result)  # None
print(hasattr(st1, 'name'))  # False

# 函数属性:
# 如果参数是当前对象,则无法删除
result = delattr(st1, 'tell')# 报错
# 如果参数是当前类,则可以删除
result = delattr(Student, 'tell')
print(result)  # None
print(hasattr(Student, 'tell'))  # False

# 不存在:直接报错

【五】面向对象内置方法(魔法方法)

__init__	:初始化类时触发
__del__		:删除类时触发
__str__		:str函数或者print函数触发
__repr__	:repr或者交互式解释器触发
__doc__		:打印类内的注释内容
__enter__	:打开文档触发
__exit__	:关闭文档触发
__getattr__ :访问不存在的属性时调用,	对象.属性
__setattr__ :设置实例对象的一个新的属性时调用,	对象.属性 = 属性值
__delattr__ :删除一个实例对象的属性时调用,	del 对象.属性
__setitem__	:列表添加值,	对象[属性]=属性值
__getitem__ :将对象当作list使用,	对象[属性]
__delitem__	:列表删除值,	del 对象[属性]
posted on 2024-05-08 19:21  晓雾-Mist  阅读(5)  评论(0编辑  收藏  举报