zoukankan      html  css  js  c++  java
  • 第十六节:内置函数补充

    通过  .  的方式访问、设置、删除对象属性的时候会触发类的内置属性__getattr__、__setattr__、__delattr__

    class Dog:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __getattr__(self, item):#在获取不存在的函数属性的时候会触发
            print("执行的是getattr")
        def __setattr__(self, key, value):#在设置对象属性的时候会触发
            self.__dict__[key] = value
        def __delattr__(self, item):#在删除对象属性的时候会触发的内置函数
            self.__dict__.pop(item)
        def run(self):
            print("%s今年%s"%(name,age)
    
     def __getattribute__(self, item):  #获取存在的函数属性的时候执行该函数
          raise AttributeError('抛出异常')#在获取不存在的函数属性的时候会抛出异常给__getattr__
    View Code
    
    

    通过键值的方式访问、设置、删除对象属性的时候会触发类的内置属性__getitem__、__setitem__、__delitem__

    class Foo:
        def __getitem__(self, item):
            print('getitem')
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            print('setitem')
            self.__dict__[key]=value
    
        def __delitem__(self, key):
            print('delitem')
            self.__dict__.pop(key)
    
    f1=Foo()
    print(f1.__dict__)
    f1['name']='sss'
    print(f1['name'])
    del f1['name']
    执行结果如下:
    {}
    setitem
    getitem
    sss
    delitem
    View Code

    类的内置属性__str__和__repr__:

    print函数在执行的时候实际上就是在调用str()函数
    在打印对象的时候实际上是在调用内置函数 str()函数 就等于  f1.__str__()  
    class Foo:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __str__(self):
            return '名字是%s 年龄是%s' %(self.name,self.age)
    #
    # f1=Foo('egon',18)
    # print(f1) #str(f1)--->f1.__str__()
    #
    # x=str(f1)
    # print(x)
    #
    # y=f1.__str__()
    # print(y)
    这三个结果是一样的,这个很重要,可以定义输出
    
    在解释器中打印的时候触发的是__repr__
    class Foo:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        # def __str__(self):
        #     return '这是str'
        def __repr__(self):
            return '名字是%s 年龄是%s' %(self.name,self.age)
    
    f1=Foo('egon',19)
    #repr(f1)---->f1.__repr__()
    print(f1) #str(f1)---》f1.__str__()------>f1.__repr__()
    
    总结:
    '''
    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常
    '''
    View Code

    类的内置属性__format__:

    format_dic={
        'ymd':'{0.year}{0.mon}{0.day}',
        'm-d-y':'{0.mon}-{0.day}-{0.year}',
        'y:m:d':'{0.year}:{0.mon}:{0.day}'
    }
    class Date:
        def __init__(self,year,mon,day):
            self.year=year
            self.mon=mon
            self.day=day
            
        def __format__(self, format_spec):
            print('我执行啦')
            print('--->',format_spec)
            if not format_spec or format_spec not in format_dic:
                format_spec='ymd'
            fm=format_dic[format_spec]
            return fm.format(self)#必须有返回值
    d1=Date(2016,12,26)
    # format(d1) #d1.__format__()  #内置方法可以直接用函数调用
    # print(format(d1))
    print(format(d1,'ymd'))
    print(format(d1,'y:m:d'))
    print(format(d1,'m-d-y'))
    print(format(d1,'m-d:y'))
    print('===========>',format(d1,'asd'))
    View Code

    类的内置属性__slots__:

    应用场景:属性较少实例较多的情况下,可用该方法(慎用)
    这样定义实例化的实例就没有属性字典了,
    class Foo:
        __slots__=['name','age']  #{'name':None,'age':None}#只能定义slots提供的属性
        # __slots__='name' #{'name':None,'age':None}#实例只能创建仅限一个属性
    
    f1=Foo()
    # f1.name='egon'
    # print(f1.name)
    
    # f1.age=18  #--->setattr----->f1.__dict__['age']=18
    
    # print(f1.__dict__)
    print(Foo.__slots__)
    print(f1.__slots__)
    f1.name='egon'
    f1.age=17
    print(f1.name)
    print(f1.age)
    View Code

     类的内置属性__doc__

    class Foo:
        '我是描述信息'
        pass
    
    class Bar(Foo):  #该属性不可继承,如果没有定义,默认是none
        pass

     类的内置属性__module__和__class__

     查看实例属于哪个模块和类

    类的内置属性析构函数__del__

    垃圾回收机制,在实例被删除的时候会触发,删除实例属性的时候不会触发,当程序执行完毕的时候会自动触发该机制回收内存

    类的内置属性__call__

    class Foo:
        def __call__(self, *args, **kwargs):
            print('实例执行啦 obj()')
    
    f1=Foo()
    
    f1() #f1的类Foo 下的__call__
    
    Foo() #Foo的类 xxx下的__call__
    一个对象之所有可以加上()运行,就是因为他调用了__call__方法

    类的内置方法__iter__和__next__

    class Foo:
        def __init__(self,n):
            self.n=n
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.n == 13:
                raise StopIteration('终止了')#跳出异常
            self.n+=1
            return self.n
    
    # l=list('hello')
    # for i in l:
    #     print(i)
    f1=Foo(10)
    # print(f1.__next__())
    # print(f1.__next__())
    # print(f1.__next__())
    # print(f1.__next__())
    
    for i in f1:  # obj=iter(f1)------------>f1.__iter__()
         print(i)  #obj.__next_()#for循环会自动捕捉异常终止循环

    描述符__get__、__set__、__del__:描述符的作用是用来代理另外一个类的属性的

    class Foo:#数据描述符
        def __get__(self, instance, owner):
            print('===>get方法')
        def __set__(self, instance, value):
            print('===>set方法',instance,value#这里的instance就是实例化的对象,value就是传的值
            instance.__dict__['x']=value #b1.__dict__
        def __delete__(self, instance):
            print('===>delete方法')
    
    
    class Bar:
        x=Foo() #在何地?#只要是在这个给类或者这个类实例化的的对象中对x进行操作,就会触发描述符的相关方法
        def __init__(self,n):
            self.x=n #b1.x=10  #触发数据描述符,因为x被数据据描述符代理了
    b1=Bar(10)
     
    Bar.x=6    #在定义类的属性的时候,优先级高于数据描述符,不会触发数据描述,会负载之前定义的描述符属性,通过属性字典可以查看
    数据描述符定义:
    一 描述符本身应该定义成新式类,被代理的类也应该是新式类
    二 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
    三 要严格遵循该优先级,优先级由高到底分别是
    1.类属性
    2.数据描述符
    3.实例属性
    4.非数据描述符
    5.找不到的属性触发__getattr__()

    1 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
    __get__():调用一个属性时,触发
    __set__():为一个属性赋值时,触发
    __delete__():采用del删除属性时,触发
    2 描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)
    3 描述符分两种
    一 数据描述符:至少实现了__get__()和__set__()
    二 非数据描述符:没有实现__set__()
  • 相关阅读:
    UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design
    UVa 1658 (拆点法 最小费用流) Admiral
    UVa 11082 (网络流建模) Matrix Decompressing
    UVa 753 (二分图最大匹配) A Plug for UNIX
    UVa 1451 (数形结合 单调栈) Average
    UVa 1471 (LIS变形) Defense Lines
    UVa 11572 (滑动窗口) Unique Snowflakes
    UVa 1606 (极角排序) Amphiphilic Carbon Molecules
    UVa 11054 Wine trading in Gergovia
    UVa 140 (枚举排列) Bandwidth
  • 原文地址:https://www.cnblogs.com/sxdpython/p/12747419.html
Copyright © 2011-2022 走看看