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__()
  • 相关阅读:
    C++类成员变量多用指针不用对象
    C++列表初始化是初始化本类自身含有的成员变量,不能直接初始化继承过来的成员变量
    std::unorder_set你插入元素的顺序不一定就是元素在里面的元素
    yolo3使用darknet卷积神经网络训练pascal voc
    windows下执行tensorflow/models的代码显示No module named 'object_detection'
    extern const 不能一起用
    常见PID里面的像素大小
    ajax 异步请求webservice(XML格式)
    剖析下聊天室
    session更换存储,实现在多台服务器共享
  • 原文地址:https://www.cnblogs.com/sxdpython/p/12747419.html
Copyright © 2011-2022 走看看