zoukankan      html  css  js  c++  java
  • 面向对象高级进阶

    一.类中的装饰器的使用:property,classmethod,staticmethod,

    property的使用:property 的作用是讲一个类的函数属性装饰成对象的一个数据属性,能够直接被对象.方法名 调用,不用去通过加()的方式调用。

    当property去装饰一个类的函数方法时,与setattr,delattr 共用时,@name.setattr @name.delattr 前面的前缀必须相同

    property的本质就实现了 get,set,del 三个方法

    class Foo:
        @property
        def AAA(self):
            print('get的时候运行我啊')
    
        @AAA.setter
        def AAA(self,value):
            print('set的时候运行我啊')
    
        @AAA.deleter
        def AAA(self):
            print('delete的时候运行我啊')
    
    #只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
    f1=Foo()
    f1.AAA
    f1.AAA='aaa'
    del f1.AAA
    class Goods:
    
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
    
        @property
        def price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount
            return new_price
    
        @price.setter
        def price(self, value):
            self.original_price = value
    
        @price.deleter
        def price(self):
            del self.original_price
    
    
    obj = Goods()
    obj.price         # 获取商品价格
    obj.price = 200   # 修改商品原价
    print(obj.price)
    del obj.price     # 删除商品原价
    property的作用实例
    #实现类型检测功能
    
    #第一关:
    class People:
        def __init__(self,name):
            self.name=name
    
        @property
        def name(self):
            return self.name
    
    # p1=People('alex') #property自动实现了set和get方法属于数据描述符,比实例属性优先级高,所以你这面写会触发property内置的set,抛出异常
    
    
    #第二关:修订版
    
    class People:
        def __init__(self,name):
            self.name=name #实例化就触发property
    
        @property
        def name(self):
            # return self.name #无限递归
            print('get------>')
            return self.DouNiWan
    
        @name.setter
        def name(self,value):
            print('set------>')
            self.DouNiWan=value
    
        @name.deleter
        def name(self):
            print('delete------>')
            del self.DouNiWan
    
    p1=People('alex') #self.name实际是存放到self.DouNiWan里
    print(p1.name)
    print(p1.name)
    print(p1.name)
    print(p1.__dict__)
    
    p1.name='egon'
    print(p1.__dict__)
    
    del p1.name
    print(p1.__dict__)
    
    
    #第三关:加上类型检查
    class People:
        def __init__(self,name):
            self.name=name #实例化就触发property
    
        @property #当property将一个类的函数属性定义与__init__中的名字一样时,
        # 由于property的优先级更高会优先执行property,而property必须通过setter方法去设置对象的新的属性
        def name(self):
            # return self.name #无限递归
            print('get------>')
            return self.DouNiWan
    
        @name.setter
        def name(self,value):
            print('set------>')
            if not isinstance(value,str):
                raise TypeError('必须是字符串类型')
            self.DouNiWan=value
    
        @name.deleter
        def name(self):
            print('delete------>')
            del self.DouNiWan
    
    p1=People('alex') #self.name实际是存放到self.DouNiWan里
    p1.name=1
    
    案例二
    property的实例1

    2.classmethod:

    class Classmethod_Demo():
        role = 'dog'
    
        @classmethod #作用及时统一了对象和类调用方法的方式,都是通过同一种方式去调用
        def func(cls):
            print(cls.role)
        def func1(self):
            print(self.role)
    
    Classmethod_Demo.func()
    Classmethod_Demo.func1() #必须传一个参数才能实现类调用去下的函数属性。

    3.staticmethod:

    class Staticmethod_Demo():
        role = 'dog'
    
        @staticmethod #作用就是当成普通的函数方法使用,类与对象都不用传参数
        def func():#注意不自动传self值了
            print("当普通方法用")
    
    Staticmethod_Demo.func()
    s =Staticmethod_Demo()
    s.func()
    #1...__new__方法的使用:就是构造方法,创建一个对象
    #单例模式:一个类从始至终只实例化一个对象,单例模式的模拟
    """
    class A:
        __issingle = False
        def __init__(self,name,age):
            print('执行的init方法')
            self.name = name
            self.age = age
        def __new__(cls, *args, **kwargs):
            print('执行的new方法')
            if cls.__issingle:
                return cls.__issingle
            cls.__issingle = object.__new__(cls)
            return cls.__issingle
    a1 = A('yuan',18)
    a2 = A('rong',18)
    a1.id = '001'
    print(id(a1),id(a2)) #在内存中的id都是相同的,实际上操作的是同一个对象
    print(a1.name,a2.name)
    print(a1.age,a2.age)
    print(a1.id,a2.id)# a2对象而言并没有id属性,用的就是a1.id,实际上就是操作同一个实例化对象
    """
    内置方法__new__的解析
    #.2.item系列的方法: 字典类型的数据就是通过item的内置方法去创建和操作的。
    """
    class A:
        def __init__(self,name):
            self.name = name
        def __getitem__(self, item):
            print('执行的getitem方法')
            return self.__dict__[item]
        def __setitem__(self, key, value):
            print('执行的setitem方法')
            self.__dict__[key] = value
            return self.__dict__
        def __delitem__(self, key):
            print('执行的delitem方法')
            del self.__dict__[key]
        def __delattr__(self, item):
            print('执行的delattr方法')
            del self.__dict__[item]
            pass
    a = A('yuan')
    # print(a.name)
    # print(a['name'])
    # a.age = 18
    a['age'] = 19  
    print(a.age)
    del a['age'] #如果执行del 语句,会执行__delitem__方法,
    del a.age # 如果执行del 语句,会执行__delattr__方法,就是两种删除的方法不一样执行调用类的方法就不一样,
    #如果即没有delitem和delattr方法就会去执行父类中的方法,都没有就执行object中的delattr方法
    print(a.age)
    """
    item系列的解析
    #__str__:可以控制对象的属性详细的说明的方法,当类中没有__str__方法时候,会调用__repr__
    """
    class A:
        def __str__(self):
            print('这是A类自己的__str__方法')
            return 'A' #可以在这里面定义自己想要定义返回的信息
    a = A()
    print(a)#当类中没有定义自己的__str__方法时,会去object中找__str__方法,会返回这个对象的内存地址
    #而当类中有自己定义的__str__方法时会优先执行执行的__str__方法,print一个对象的时候会自动执行该对象下的
    #__str__方法,该对象的类中没有,找父类,父类没有,找object中。
    print(str(a))
    %s,str() 就是调用类下的__str__方法
    """
    __str__方法的解析
    # __repr__:将对象的原始数据格式打印到终端,当类中没有__repr__时候,不能调用__str__方法。
    #%r repr() 就是调用了类下的__repr__方法
    """
    class A:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def __repr__(self):
            print('这是自己的repr方法')
            return str(self.__dict__) #跟str的返回值一样,必须返回一个字符串
    a = A('yuan',18)
    print('%r'% a)#相当于调用_repr__方法
    print(repr(a))
    """
    __repr__的解析
    #__del__:析构函数
    # 作用一般是在文件打开后做的收尾工作,与内置的垃圾回收装置相关
    """
    import time
    class A:
        def __del__(self):
            print('执行自己的del方法')
    a = A()  #如果一个程序代码都执行完之后,会自动执行对象中的__del__方法,即没有手动
    # del 对象也会执行__del__里面的代码,与python中的垃圾回收装备有关联关系。
    time.sleep(3) 
    """
    析构函数__del__的解析
    #__call__:当一个对象被调用的时候会自动执行该对象下的__call__方法
    """
    class A:
        pass
        # def __call__(self, *args, **kwargs):
        #     print('执行自己的call方法')
    a = A() #相当于执行了 a() ,就是自动执行该对象下的__call__方法
    #如果没有该对象下没有__call__方法,及时提示报错,只会从该对象的父类中查找是否有
    #__call__方法,不会去object中找寻__call__方法,
    a()
    """
    __call__方法的解析
    #__eq__:判断两个对象是否相等,默认的是比较两个对象的内存地址,如果需要重新
    #定制自己的判断相等的方法,只需要在__eq__中定义自己的方法
    """
    class A:
        def __init__(self,name):
            self.name = name
    
        def __eq__(self, other):
            if self.name == other.name:
                return True
    a1 = A('yuan')
    a2 = A('yuan')
    print(a1 == a2) # 如果没有定制自己的__eq__,就默认执行object中的__eq__,默认比较两个对象的内存地址
    """
    __eq__方法的解析
    #__hash__:获得对象的hash值
    """
    a = 10
    a1 ='abc'
    l = [1,2,3]
    print(hash(a))
    print(hash(a1))
    print(hash(l)) #可变数据类型是不可以被hash的
    """
    hash()内置函数
    #内置方法的实例,使用内置方法会使代码更加的优美
    #1 实例一  模拟一副扑克牌
    """
    import random
    import json
    from collections import namedtuple
    from random import shuffle
    Card = namedtuple('Card',['rank','suits'])
    
    class Poke:
        ranks = [str(rank) for rank in range(1,11)] + list('JQKA')
        suits = ['红心','黑桃','方块','梅花']
        def __init__(self):
            self.__cards = [Card(rank,suit) for rank in Poke.ranks for suit in Poke.suits]
        def __getitem__(self, item): #想要通过[]的形式去取值,就要设置自己的__len__方法,
            return self.__cards[item]
        def __len__(self):
            return len(self.__cards)
        def __setitem__(self, key, value):
            self.__cards[key] = value
        def __str__(self):#想要定义自己的__str__就必须要定义自己的__setitem__方法
            return json.dumps(self.__cards,ensure_ascii=False)#__str__可视化要进行json序列化一下
    
    c = Poke()
    print(c[0]) #取得是第一张牌
    print(c[0][0])#取得是第一张牌的数字
    print(c[0][1])#取得是第一张牌的花色
    print(random.choice(c))
    print(c)
    shuffle(c)#完成洗牌操作
    print(c)
    print(c[:5])#直接去通过__getitem__方法去实现的,类似于用字典的关键字去取值一样
    """
    内置方法的结合使用:扑克牌的模拟
    #2.实例一  一道面试题
    #1.有100的对象,名字和性别相同,但年龄不同
    
    class A:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def __eq__(self, other):#加了__eq__才能完成去重,内置判断去重不是简单的判断hash,还是与__eq__相关联
            if self.name == other.name and self.sex == other.sex:
                return True
            return False
        def __hash__(self):
            return hash(self.name + self.sex)
    
    a1 = A('yuan','male',18)
    a2 = A('yuan','male',18)
    
    
    print(set((a1,a2)))# 还是没有完成去重,加了__hash__和__eq__才能完成去重
    """
    如何去实现去重的机制
    a1 = A('yuan','male',18)
    a2 = A('yuan','male',19)
    print(a1)
    print(a2)
    print(a2.__dict__)
    
    res =set((a2,a1))# 还是没有完成去重,加了__hash__和__eq__才能完成去重
    print(list(res)[0].__dict__) #完成了去重,得到去重后的值
  • 相关阅读:
    java 容器
    Java容器有哪些?
    java容器---集合总结
    Java中的String,StringBuilder,StringBuffer三者的区别
    Socket心跳包机制
    JAVA实现简单的RPC框架
    redis、kafka、rabittMQ对比
    idea+maven无法自动加载jar包
    myeclipse 上安装 Maven3
    linux_开发软件安装=命令步骤
  • 原文地址:https://www.cnblogs.com/njzy-yuan/p/10745261.html
Copyright © 2011-2022 走看看