zoukankan      html  css  js  c++  java
  • OOP 内置函数

    内置函数:类中存在一些名字带有__(双下滑线)开头的内置函数,这些函数会在某些时候被自动调用

    1.  isinstance &  issubclass

      isinstance:判断一个对象是否是某个类的实例

      用法:isinstance(obj, cls)    检查 obj 对象是否是 cls 类  (不仅限于类中)

      issubclass:判断一个类是否是另一个类的子类

      用法:issubclass(sub, super)    检查 sub 类是否是 super 类的派生类

    2. __str__

      用法:调用 str 函数或者 print 函数时(输出结果为字符串)自动执行,返回值作为显示内容

      使用场景:我们可以利用该函数来自定义对象的打印格式(不设置则默认解释器里面内置的)

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def __str__(self):
            return '我叫%s,我今年%s岁了' % (self.name, self.age)  # 可以自定义输出格式
    
    
    p = Person('zhao', 24)
    print(p)  # 我叫zhao,我今年24岁了

     

    3. __del__

      当对象在内存中被释放时(手动删除对象、程序运行结束时),会自动触发执行

      使用场景:当你的对象在使用过程中打开了不属于解释器的资源:例如文件、网络端口

    class File:
        def __del__(self):
            print('已删除...')
    
    f = File()
    del f  # 已删除...

    4. __call__

      在对象被调用时执行

      用法:对象()

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

    class Person:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __call__(self, *args, **kwargs):
            print('执行我了')
            print(*args)
            print(**kwargs)
    
    
    p = Person('zhao', 24)  # 执行 __init__
    p()  # 执行我了  执行 __call__
    p('hobby = read')  # 执行我了  hobby = read    执行 __call__

     

    5. __slots__

      该属性是一个类属性,用于优化对象内存占用

      优化的原理:将原本不固定的属性数量,变得固定了

      这样的解释器就不会为这个对象创建名称空间,所以__dict__也没了 

      从而达到减少内存开销的效果

      用法:

    class Person:
        __slots__ = ['name']
    
    p = Person()
    p.name = 'jake'
    print(p.__slots__)  # ['name']
    p.age = 18  # 报错,当类中出现了slots时将导致这个类的对象无法在添加新的属性
    ''' Traceback (most recent call last): File "D:/代码练习/7.29/clots.py", line 10, in <module> p.age = 18 AttributeError: 'Person' object has no attribute 'age '''' print(p.__dict__) # 报错,使用slots后就不存在__dict__ ''' AttributeError: 'Person' object has no attribute 'age '''' ^ SyntaxError: EOL while scanning string literal '''

    6. __getattribute__ & __getattr__ & __setattr__ & __delattr__

      __getattribute__:使用 点语法 调用 属性的时候触发,无论属性是否存在都会执行

      __getattr__:使用 点语法 调用 属性且属性不存在的时候才会触发

      __setattr__:使用 点语法 添加/修改 属性会触发它的执行

      __delattr__:使用 点语法 删除 属性的时候会触发

      注意:当 __getattribute__ 与 __getattr__ 同时存在时,仅执行 __getattribute__

    class Person:
        def __init__(self,name):
            self.name = name
    
        def __getattr__(self, item):
            return self.__dict__[item]
    
        def __setattr__(self, key, value):
            self.__dict__[key] = value
    
        def __delattr__(self, item):
            del self.__dict__[item]
    
    
    p = Person('zhao')
    print(p.__dict__)  # {'name': 'zhao'} 此时只有这么一个元素
    
    p.age = 24
    print(p.__dict__)  # {'name': 'zhao', 'age': 24}  触发了__setattr__,成功添加进去
    print(p.age)  # 24  触发了__getattr__,成功访问到新添加进去的值
    
    del p.age  # 触发__delattr__,成功删除p.age属性
    print(p.__dict__)  # {'name': 'zhao'}

    7. __getitem__ & __setitem__ & __delitem__

      __getitem__:使用 key 的形式获取属性时触发

      __setitem__:使用 key 的形式添加/修改属性时触发

      __delitem__:使用 key 的形式删除属性时触发

    class Person:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __getitem__(self, item):
            return self.__dict__[item]
    
        def __setitem__(self, key, value):
            self.__dict__[key] = value
    
        def __delitem__(self, key):
            self.__dict__.pop(key)
    
    
    p = Person('zhao', 24)
    print(p.__dict__)  # {'name': 'zhao', 'age': 24}
    
    p['name']  # 触发了__getitem__方法
    print(p['name'])  # zhao
    
    p['age'] = 18  # 触发了__setitem__方法
    print(p['age'])  # 18
    
    del p['name']  # 触发__delitem__方法
    print(p.__dict__)  # {'age': 18}

    8. __gt__ & __lt__ & __eq__ (运算符重载)

      当我们在使用某个符号时,python解释器都会为这个符号定义一个含义,同时调用对应的处理函数

      当我们需要自定义对象的比较规则时,就可在子类中覆盖大于、等于、小于等一系列方法....

    class Person:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def __gt__(self, other):  # 自定义比较的方法,在这里比较的是对象中的年龄,覆盖了原来的   other指的是另一个参与比较的对象
            return self.age > other.age
    
        def __lt__(self, other):  # 自定义比较的方法,在这里比较的是对象中的年龄,覆盖了原来的   other指的是另一个参与比较的对象
            return self.age < other.age
    
        def __eq__(self, other):  # 自定义比较的方法,在这里比较的是对象中的年龄,覆盖了原来的   other指的是另一个参与比较的对象
            if self.age == other.age:
                return True
            return False
    
    
    p = Person('', 24)
    p1 = Person('', 18)
    p2 = Person('', 18)
    
    print(p > p1)  # True
    print(p < p1)  # False
    print(p1 == p2)  # True

     

    9. __iter__ & __next__ (迭代器协议)

      回顾:迭代器是指具有__iter__和__next__的对象

      因此:我们可以为对象增加这两个方法来让对象变成一个迭代器

    '''
    定义自己的range方法
    '''
    
    class MyRange:  # 定义自己的range
        def __init__(self,start,end,step):
            self.start = start  # 起始
            self.end = end  # 结束
            self.step = step  # 步长
    
        def __iter__(self):
            return self  # 迭代器对象调用__iter__方法后还是迭代器,生成器对象调用__iter__方法后生成迭代器对象
    
        def __next__(self):
            a = self.start
            self.start += self.step
            if a < self.end:
                return a
            else:
                raise StopIteration  # 不知道这是啥,也没讲,也不敢问
    
    
    myrange = MyRange(1,6,2)
    for i in myrange:
        print(i)  # 1 3 5

    10. __enter__ & __exit__ (上下文管理)

      上下文:context   在这个代码中python解释器分析出你的代码想要做的事情,然后在结束的时候自动帮你将资源释放了

      with中的所有代码都在一个上下文中,你可以把他理解为一个代码范围---------仅在上下文范围内有效

      __enter__出现 with语句,对象的 __enter__ 被触发,有返回值则赋值给 as 声明的变量

      __exit__with 中代码块执行完毕时执行

      只要一个类实现了这两个方法就可以被 with 语句使用

    class MyOpen:  # 定义自己的打开
        def __init__(self, filepath, mode='r', encoding='utf-8'):
            self.filepath = filepath
            self.mode = mode
            self.encoding = encoding
    
        def __enter__(self):
            self.f = open(self.filepath, mode=self.mode, encoding=self.encoding)
            return self.f
    
        def __exit__(self, exc_type, exc_val, exc_tb):  # 三个参数分别代表异常类型,异常值和追溯信息
            self.f.close()
            print('文件关闭了')
         # return True with MyOpen(
    'xxx.txt', 'a') as f: print(f) # <_io.TextIOWrapper name='xxx.txt' mode='a' encoding='utf-8'> 这是啥..... f.write('你好啊!') # 结果成功写入
       f.wasdf #抛出异常,交给__exit__处理
    # 反正最后自己定义的MyOpen成功了,与内置的open具有相同的效果

    注:1.  with 语句中代码块出现异常时,会立即触发方法 __exit__ 的执行,并将异常信息错误参数传入

      2.  with 语句中代码块未出现异常正常结束时也会触发方法 __exit__ 的执行,此时参数中的异常信息为空

      3. 如果 __exit__ 返回值为 True ,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行

    总结:

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

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

    *******与del的区别:del管理的是对象的生命周期 ,会在对象销毁时执行清理 

      

  • 相关阅读:
    windows 物理内存获取
    windbg-.process切换进程(内核)
    cnetos 6.7彻底解决vmware NAT网络问题
    优秀的博客链接地址
    使用Spring MVC统一异常处理实战
    active mq 配置
    socket demo程序
    flume 中的 hdfs sink round 和roll
    软链接与硬链接
    flume A simple example
  • 原文地址:https://www.cnblogs.com/pupy/p/11266477.html
Copyright © 2011-2022 走看看