• Python之各种内置方法


    1、attr 系列

    class foo:
        def __init__(self,NAME):
            self.name=NAME
    
        def __setattr__(self, key, value):
            # 作用:可以对 value 进行类型限制
            if not isinstance(value,str): # 对 value 限制只能是字符串
                raise TypeError('must be str')
            # print('setattr----key:%s,value:%s'%(key,value))
            # print(type(key)) # key 是字符串类型
            # print(type(value))
            # self.key=value  # key 是字符串类型,self.属性,属性不能为字符串类型,不能这样赋值
            # setattr(self,key,value) # 跟上面一样 self.key=valuse 会触发 setattr 的执行,会造成递归
            self.__dict__[key]=value # 直接在对象的 dict 字典里面操作
    
        def __delattr__(self, item):
            print('delattr:%s'%item)
            # del self.__dict__[item]  # 同样,删除直接去删除对象的字典,法1
            self.__dict__.pop(item)  # 法2
    
        def __getattr__(self, item):
            print('getattr:%s'%item)
    
    
    
    f1=foo('egon')  # f1.name='egon' 赋值操作会先触发setattr 的执行
    
    f1.age='18'
    del f1.age
    print(f1.__dict__)
    
    
    getattr 单独拿出来
    class foo:
        def __init__(self, NAME):
            self.name = NAME
    
        # 只有属性不存在才会触发 getattr 的执行
        def __getattr__(self, item):
            print('getattr:%s %s' % (item,type(item)))
    
    
    f1 = foo('egon')  # f1.name='egon' 赋值操作会先触发setattr 的执行
    
    # print(f1.name)
    print(f1.xxxx)  # 属性不存在才会触发 getattr 的执行
    View Code

    2、item 系列

    __setitem__(self,key,value):当对类中的某个属性进行"赋值"时触发的函数(只有使用字典赋值的方式时才会触发此方法的执行)
    与Attr系列的区分:__setattr__(self):是在对象打点儿的方式赋值时,才会触发的方法
    
    class Foo:
        def __setitem__(self, key, value):
            print(key,"获得",value)
    f = Foo()
    f["name"] = "egon"   value = egon
    __setitem__
    __delitem__(self,key):当类中的某个属性被删除时,触发此方法(只有使用del字典方式删除属性时,才会触发此方法)
    与Attr系列的区分:__delattr__(self):使用del类打点儿属性的方式删除属性,才会触发此方法
    
    class Foo:
        name = "egon"
        def __delitem__(self, key):
            print(key,"已被删除")
    f = Foo()
    del f["name"]
    __delitem__
    __getitem__(self,item):当调用类中的属性或方法时触发此方法的执行(只在使用类[key]字典的方式调用时,才会触发此方法)
    与Attr系列的区分:其实这里已经很明显了,__getattr__(self):是类打点儿调用且命名空间没有发现名字的情况下,触发此方法
    class Foo:
        name = "egon"
        def __getitem__(self, item):
            print(item,"已被调用")
    f = Foo()
    f["name"]
    __getitem__

    3、__slots__

    __slots__:其实就是将类中的名称锁定,实例化对象,只可以赋值和调用,不可以删除属性和增加新的属性

    应用场景:当实例化几万个对象的时候,每个对象都会生成一个名称空间__dict__,而每一个名称空间都会各自占用一个内存,造成内存的浪费,用 __slots__,不用再产生 dict 了,省内存,对象的 dict 都统一用类的 dict,属性都是用 slots 给定义的

    class Foo:
        __slots__ = ["x","y"]#在类中定义属性x和y
    f = Foo()#实例化Foo
    f.x = 1#此时我们可以使用实例化对象调用类中的属性x
    f.y = 2
    #如果现在,我们在实例化对象中增加一个z
    f.z = 3
    #会得到如下错误
    #AttributeError: 'Foo' object has no attribute 'z'
    #也就是不可以,对实例化对象增加新的属性
    #如果现在,我们在实例化对象中删除一个x
    del f.x#此时程序执行并不会出错,但是我们打印一下Foo的命名空间
    print(Foo.__dict__)
    #{'__doc__': None, 'y': <member 'y' of 'Foo' objects>, '__module__': '__main__', 'x': <member 'x' of 'Foo' objects>, '__slots__': ['x', 'y']}
    #依然可以看到x的存在,所以,实例化对象不可以删除__slots__定义的属性
    例1
    class Foo:
        __slots__ = ["x","y"]
    Foo.__slots__ = "z"
    print(Foo.__dict__)
    #{'__doc__': None, 'x': <member 'x' of 'Foo' objects>, '__slots__': 'z', '__module__': '__main__', 'y': <member 'y' of 'Foo' objects>}
    del Foo.x
    print(Foo.__dict__)
    #{'__doc__': None, '__slots__': 'z', '__module__': '__main__', 'y': <member 'y' of 'Foo' objects>}
    # f.z=3  对象也无法赋值
    __slots__只是针对实例化对象的禁锢,直接对类中的属性进行修改,是可以的
    例2

    4、__next__ 和 __iter__

    class foo:
        def __init__(self,start):
            self.start=start
    
        def __next__(self):
            return self
    
        def __iter__(self):
            n=self.start
            self.start=+1
            return self
    
    
    f=foo(0)
    print(next(f))  # f.__next__()
    print(next(f))  # f.__next__()
    
    for i in f:  # 执行 i=f.__iter__ 方法,转化为一个迭代器
        print(i)   #  next(i) 执行 next 方法
    View Code

    5、__del__

    这个是在回收实例化对象时触发执行的方法

    每当 del 实例化对象时会触发

    或者是程序结束时,会触发,总之就是实例化对象失效时都会执行__del__方法

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的

    class Foo:
        def __del__(self):
            print(self,"被释放掉了")
    
    f = Foo()
    print(f)
    del f
    
    
    
    import time
    class Open:
        def __init__(self,file,mode='r',encoding='utf8'):
            self.x=open(file,mode=mode,encoding=encoding)
            self.file=file
            self.mode=mode
            self.encoding=encoding
    
        def write(self):
            pass
    
        def __del__(self):
            print('del')
            self.x.close()
    
    
    # Open('a.txt','w') 需要开辟一个内存空间来存放值,产生一个对象,变量 f 与它进行绑定,此时 f 在引用,引用计数不为0
    # 当引用计数为 0 的时候,就去对象里面找 析构函数 del
    f=Open('a.txt','w')  #  当跑完程序,f 与Open 的绑定关系就解除,触发 del 的执行,回收值的内存
    del f  # 下面程序还没跑完,就执行 del,删除 f ,Open 没有被引用,引用计数为 0 ,回收 Open
    time.sleep(1000)
    
    
    # 注意,如果没有 del 方法,对象被删除后,不会被立即回收,python回收机制会定期去回收
    View Code

    6、__str__

    class Pepole:
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def __str__(self):  # 
            return 'abc'  # __str__ 方法必须返回字符串
    
    obj=Pepole('egon',18)
    print(obj)  # 当打印对象的时候触发 __str__方法
    View Code

    7、__enter__和__exit__

    所谓上下文管理协议,就是咱们打开文件时常用的一种方法:with

    __enter__(self):当with开始运行的时候触发此方法的运行

    __exit__(self, exc_type, exc_val, exc_tb):当with运行结束之后触发此方法的运行

    exc_type如果抛出异常,这里获取异常的类型

    exc_val如果抛出异常,这里显示异常内容

    exc_tb如果抛出异常,这里显示所在位置

    用途或者说好处:

    1.使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预

    2.在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处

    class Foo:
        def __enter__(self):
            print('=======================》enter')
            return 111111111111111
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print('exit')
            print('exc_type',exc_type)
            print('exc_val',exc_val)
            print('exc_tb',exc_tb)
            return True  # 如果不加这一行,表示抓到报错,整个程序退出,不再往下执行
        # 如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
    
    
    # with Foo(): #res=Foo().__enter__()
    #     pass
    
    with Foo() as obj: #res=Foo().__enter__() #obj=res
        print('with foo的自代码块',obj)
        raise NameError('名字没有定义') # with语句中代码块出现异常,则with后的代码都无法执行
            print('************************************')
    
    # 执行与否,看 exit 返回的是否 true
    print('1111111111111111111111111111111111111111')
    例1
    class Open:
        def __init__(self,file,mode='r',encoding='utf8'):
            # 使用系统函数open()传入相应打开文件所需的参数,将文件句柄传递给self.f
            self.f=open(file,mode=mode,encoding=encoding)
    
        def __enter__(self):
            return self 
        # 这里要返回 self 而不是 self.f,self.f 是调用真实的 open 文件操作的方法
            # 这里 self 调用的是 Open 类里面的各个函数属性
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.f.close()
            print('关闭')
    
        def write(self,line): #自己定义write方法
            print('ok')
            self.f.write(line) #使用self.f 文件句柄 write 方法将内容写入文件
    
        # 利用__getattr__(),Attr系列中的getattr,当对象没有找到Open中传递过来的名字时,调用此方法
        def __getattr__(self, item):
            return getattr(self,item) # 返回self.f 文件句柄中,被对象调用,且不在Open类中的名字
    
    with Open('a.txt','w',encoding='utf8') as obj:
        # obj=Open('a.txt','w',encoding='utf8')
        obj.write('123')
        # 调用的是类里面的 write 方法,方法里面有 obj.f.write 调用真实的 write
    例2

    8、__doc__

    描述信息用的

    class Foo:
        '我是描述信息'
        pass
    
    print(Foo.__doc__)
    
    
    class Foo:
        '我是描述信息'
        pass
    
    class Bar(Foo):
        pass
    print(Bar.__doc__) #该属性无法继承给子类
    
    该属性无法被继承
    View Code

    9、__call__

    对象后面加括号,触发执行。

    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class Foo:
    
        def __init__(self):
            pass
        
        def __call__(self, *args, **kwargs):
    
            print('__call__')
    
    
    obj = Foo() # 执行 __init__
    obj()       # 执行 __call__
    View Code

    .

  • 相关阅读:
    The Node.js Event Loop, Timers, and process.nextTick()
    Main event loop
    Why should I avoid blocking the Event Loop and the Worker Pool?
    HTML Standard系列:Event loop、requestIdleCallback 和 requestAnimationFrame
    在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
    多线程 主线程
    mvvm
    跨库事务
    nginx 死循环
    nginx proxy pass redirects ignore port
  • 原文地址:https://www.cnblogs.com/tootooman/p/9225371.html
Copyright © 2020-2023  润新知