Python Note -- Day 14. 面向对象 - 高阶

本文详细介绍了Python中的描述符,包括基本语法、应用案例和三种定义方式,强调其作为类成员管理操作的角色。同时,讨论了设计模式的概念,如单例模式和Mix-in混合设计模式,探讨了它们在代码设计和重用性中的价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

19.5 描述符

当一个类中,包含了三个魔术方法(__get__、__set__、__del__)之一,或者全部时,那么这个类就称为 描述符类

19.5.1 描述符的基本语法

  • 作用:
    对一个类中的某个成员进行一个详细的管理操作(获取、赋值、删除)
    描述符就是代理了一个类中成员的操作,只能定义为类的属性,属于类

  • 使用格式:
    把描述符类赋值给一个需要代理的类中的成员属性

一个类中的成员是一个描述符类的对象
当对这个类中的成员进行操作时,可以理解为就是对另一个对象的操作

# 定义描述符类
class Personname():
    __name = 'name1'

    def __get__(self, instance, owner):
        return self.__name

    def __set__(self, instance, value):
        self.__name = value      # 注意 ! 
        
    def __del__(self):
        # del self.__name
        print('不允许删除')
        
class Person():
    # 把类中的一个属性,交给描述符类来实现
    name = Personname()
z = Person()
z.name = 'zhangsan'
print(z.name)

19.5.2 描述符的应用案例

  • 定义一个学生类,记录学生的ID,名字,分数
  • 要求学员的分数只能在0-100
# 限制分数范围
'''
方法1:__init__中判断
        if score in range(0,101):
            self.score = score
该方法只在对象初始化时有效!!

方法2:__setattr__
    def __setattr__(self, key, value):
        # 检测是否是给score进行赋值操作
        if key == 'score':
            if value in range(0, 101):
                object.__setattr__(self, key, value)
            else:
                print('wrong')
        else:
            object.__setattr__(self,key,value)
            
   假如学生分数不止一个,且代码是否简练?
   
方法3:使用描述符类代理
    1,定义score描述符类
    2,把学生类中score这个成员交给描述符类进行代理
    3,只要在代理的描述符类中对分数进行赋值和获取
     
'''

# 使用描述符类代理score属性

class Score():
    __score = 0

    def __get__(self, instance, owner):
        return self.__score

    def __set__(self, instance, value):
        if value in range(101):
            self.__score = value

        else:
            print('wrong score')


class Student():

    score = Score()

    def __init__(self,id,name,score):
        self.id = id
        self.name = name
        self.score = score

    def Returnme(self):
        info = f'''
        Student ID : {self.id}
        Student Name : {self.name}
        Student Score : {self.score}
        '''
        print(info)

# 实例化对象
one = Student('20211001','wangwu',99)
one.Returnme()
one.score = 120
one.score = 100
one.Returnme()

19.5.3 描述符的三种定义方式

1.格式一:通过定义描述符来实现, 推荐

class ScoreManage():
    def __get__(self, instance, owner):
        pass
    
    def __set__(self, instance, value):
        pass
    
    def __delete__(self, instance):
        pass
    
class Student():
    score = ScoreManage()

2.格式二:使用property 函数实现

class Student():

    def getscore(self):
        print('getscore')

    def setscore(self,value):
        print('setscore',value)

    def delscore(self):
        print('delscore')

    # 在 property 函数中指定对应的三个方法(固定顺序对应!),1__get__2,__set__3,__del__
    score = property(getscore,setscore,delscore)

zz = Student()
print(zz.score)  # getscore /n None
zz.score = 200
del zz.score

3.格式三:使用 @property 装饰器语法实现

class Student():

    __score = 0

    @property
    def score(self):
        print('getscore')
        return self.__score

    @score.setter
    def score(self,value):
        print('setscore',value)
        self.__score = value

    @score.deleter
    def score(self):
        print('delscore')
        del self.__score

zs = Student()
zs.score
print(zs.score)
zs.score = 122
print(zs.score)
del zs.score

19.6 设计模式

前人为完成某个功能或需求,根据经验和总结,对实现的代码步骤和代码设计进行了总结和归纳,成为了实现某个需求的经典模式。

设计模式并不是固定的代码格式,而是一种面向对象编程的设计

19.6.1 单例(单态)设计模式

当前脚本中,同一个类只能创建出一个对象去使用

'''
干扰对类的无限使用
实现单例的案例,思考:
单例和婚姻法,特别像,一个人只能有一个合法的结婚对象:
在社会中如何完成?
到民政局登记,需要检查户口本,看是否属于已婚状态,若未婚,可以登记

1.需要有一个方法,可以控制对象的创建
    构造方法 __new__
2.在此方法中,需要检测是否有对象 , 构造方法在,需要加判断条件 
    需要有一个标识来存储和表示是否有对象
        创建一个属性,进行存储,默认值为None
3.在创建对象的方法中就可以检测和判断
    若无对象,则创建对象,并存储,返回对象
    若有,则直接返回对象,不需创建新对象
'''

class Demo():

    # 2.定义私有属性存储对象
    __obj = None

    # 1.定义构造方法
    def __new__(cls, *args, **kwargs):
        # 3.创建对象过程,判断是否有对象
        if not cls.__obj:
            # 判断若没有对象,则创建并存储
            cls.__obj = object.__new__(cls)
        
        return cls.__obj


a = Demo()
b = Demo()
print(a)
print(b)

注意:要背下来!!

19.6.2 Mix-in混合设计模式

'''
交通工具类中包含汽车,飞机,直升机等,如何定义飞行功能

交通工具类和飞行器类
但是 1.出现类多继承,违背‘is-a’ 2.飞行器这个类容易造成误解
解决方案:将飞行器类定义为一个Mixin混合类
相当于把飞行器类,作为一个扩展的功能,来扩展其他类
'''

class Vehicle():

    def carry(self):
        print('transfer the groceries')

    def carry2(self):
        print('transfer passengers')
        
class FlyingMixin():
    
    def fly(self):
        print('fly in the sky')

class Car(Vehicle):
    pass

class Airplane(Vehicle,FlyingMixin):
    pass

class Helicopter(Vehicle,FlyingMixin):
    pass
  • python中的Mixin是通过多继承实现的
  • Mixin 必须是表示一种功能,而不是一个对象
  • Mixin 的功能必须是单一的,如果多个功能,就多定义几个Mixin类
  • Mixin类通常不单独使用,而是混合到其他类中,去增加功能
  • Mixin类不依赖子类的实现,即便子类不继承Mixin,也能正常运行,就是少了一些功能

使用Mixin类的好处

1.Mixin混合类的设计模式,在部队类的内容修改的前提下,扩展了类的功能
2.提高代码的重用性,使得代码结构更加简单清晰
3.可以根据开发需要任意调整功能
4.避免涉及多层次的复杂的继承关系

19.6.3 设计模式的抽象类(了解)

抽象类是一个特殊的类:
1.抽象类不能用,不能直接实例化成为一个对象
2.抽象类中包含抽象方法,抽象方法就是没有实现代码的方法
3.抽象类需要子类继承,并重写父类的抽象方法,才可以使用

抽象类一般应用在程序设计,程序设计中一般是要对功能和需求进行规划,其中有一些需求是明确并且可以完成的,但是也可能会有些是不明确的,不确定需要怎样实现
此时就可以把这个不确定怎么实现或者需要后面再去实现的方法,定义为抽象方法(只定义方法名,不写具体代码)

举例:
公司有一项新的产品需要开发,交给开发部门boss
boss开始设计如何完成产品开发
需要不同的技术,不同的人来完成
boss完成了部分功能,还有一部分定义了需求,但没有具体实现,需要其他人

已完成部分就是 普通方法,未完成的就可以理解为抽象方法

import abc

# 定义为抽象类,这个类的metaclass的属性必须为 metaclass=abc.ABCmeta
class Writecode (metaclass=abc.ABCmeta):

    # 需要抽象的方法,需要使用装饰器
    @abc.abstractmethod
    def write_php(self):
        pass

    def write_java(self):
        print('finished java')

    def write_python(self):
        print('completed python')
# 定义后,抽象类不能直接实例化对象
# ob = Writecode()
# TypeError:

# 定义子类,继承抽象类,并实现抽象类中的抽象方法
class Demo(Writecode):
    def write_php(self):
        print('achieve php')
a = Demo()
print(a)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值