zoukankan      html  css  js  c++  java
  • 第十三章、面向过程高阶

    第十三章、面向过程高阶

    一、isinstance和issubclass

    1. isintance和type的区别

      class A():
          pass
      
      class B(A):
          pass
      
      b=B()
      
      print(type(b))#谁实例化的对象就是谁
      #------------------------
      <class '__main__.B'>
      #------------------------
      print(isinstance(b,A))#True
      print(isinstance(b,B))#True
      
    2. isinstance和issubclass的区别

      issubclass() 方法用于判断参数 class 是否是类型参数 classinfo 的子类。

      • 语法

        以下是 issubclass() 方法的语法:

        issubclass(class, classinfo)

      • 参数

        class --(子) 类。

        classinfo -- 类。

      • 返回值

        如果 class 是 classinfo 的子类返回 True,否则返回 False。

    二、反射(hasattr、getattr、setattr和delattr)

    反射的本质:F.__dict__[run](p)所以能像操作字典那样操作增删改查

    . hasattr:判断一个方法是否存在与这个类中 用法:hasattr(对象,字符串)
    2. getattr:根据字符串去获取obj对象里的对应的方法的内存地址,加"()"括号即可执行。或者返回属性值 用法:getattr(对象,字符串)
    3. setattr:通过setattr将外部的一个函数绑定到实例中 用法:setattr(对象,属性,属性值)
    4. delattr:删除一个实例或者类中的方法
    
    • hasattr()

      print(hasattr(peo1, 'eat'))  # peo1.eat
      -------------------------------
      True
      
    • getattr()

      class People:
          country = 'China'
      
          def __init__(self, name):
              self.name = name
      
          def eat(self):
              print('%s is eating' % self.name)
      
          def xxxxx(self):
              print('调用我了')
      
      
      peo1 = People('nick')
      getattr(peo1, 'xxxxx')()#获取了方法地址,括号调用方法
      --------------------------------------------------
      调用我了
      --------------------------------------------------
      getattr(dd, inp_func,None)#没有找到inp_func会返回none
      
    • setattr()

      setattr(peo1, 'age', 18)  # peo1.age=18
      print(peo1.age)
      print(peo1.__dict__)
      ------------------------------------------
      18
      {'name': 'nick', 'age': 18}
      
      
    • delattr()

      delattr(peo1, 'name')  # del peo1.name
      print(peo1.__dict__)
      ----------------------------------------
      {'age': 18}
      
    • 模块应用

    • # dynamic.py
      imp = input("请输入模块:")
      dd = __import__(imp)
      # 等价于import imp
      inp_func = input("请输入要执行的函数:")
      
      f = getattr(dd, inp_func,None)  # 作用:从导入模块中找到你需要调用的函数inp_func,然后返回一个该函数的引用.没有找到就烦会None
      
      f()  # 执行该函数
      

    三、__setattr__和__delattr__和__getattr__

    class Foo:
        x = 1
    
        def __init__(self, y):
            self.y = y
    
        def __getattr__(self, item):
            print('----> from getattr:你找的属性不存在')
    
        def __setattr__(self, key, value):
            print('----> from setattr')
            # self.key = value  # 这就无限递归了,你好好想想
            # self.__dict__[key] = value  # 应该使用它
    
        def __delattr__(self, item):
            print('----> from delattr')
            # del self.item  # 无限递归了
            self.__dict__.pop(item)
    
    
    f1 = Foo(10)
    
    print(f1.__dict__)  # 因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
    f1.z = 3
    print(f1.__dict__)
    
    f1.__dict__['a'] = 3  # 我们可以直接修改属性字典,来完成添加/修改属性的操作
    del f1.a
    print(f1.__dict__)
    
    class A:
        def __init__(self,name):
            self.name='nick'
    
        def __delattr__(self, item):#重写了delattr(),没有删除的效果
            print(f'删了{item}')
    
    p=A('name')
    
    print(p.name)
    
    delattr(p,'name')
    print(p.name)
    ---------------------------------------------
    nick
    删了name
    nick
    

    四、__call__

    **说明:凡是可以把一对括号()应用到某个对象身上都可称之为可调用对象,判断对象是否为可调用对象可以用函数 callable **

    如果在类中实现了 call 方法,那么实例对象也将成为一个可调用对象,

    class Entity:
    '''调用实体来改变实体的位置。'''
    
    def __init__(self, size, x, y):
        self.x, self.y = x, y
        self.size = size
    
    def __call__(self, x, y):
        '''改变实体的位置'''
        self.x, self.y = x, y
    
    e = Entity(1, 2, 3) // 创建实例
    e(4, 5) //实例可以象函数那样执行,并传入x y值,修改对象的x y 
    
    print(e.x,e.y)
    -----------------------
    4 5
    

    五、__str__和__repr__

    • __str__

      class Foo:
          def __init__(self, name, age):
              """对象实例化的时候自动触发"""
              self.name = name
              self.age = age
      
          def __str__(self):
              return f'我的名字{self.name},年龄{self.age}'  
              #return [1]# 如果不返回字符串类型,则会报错
      
      
      obj = Foo('nick', 18)
      print(obj)
      -----------------------------------------
      我的名字nick,年龄18
      
    • __repr__

      • str函数或者print函数--->obj.str()
      • repr或者交互式解释器--->obj.repr()
      • 如果__str__没有被定义,那么就会使用__repr__来代替输出
      • 注意:这俩方法的返回值必须是字符串,否则抛出异常

    六、实现文件上下文管理(__enter__和__exit__)

    • 我们知道在操作文件对象的时候可以这么写
    with open('a.txt') as f:
        '代码块'
    
    • 上述叫做上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法

    • exit()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行

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

      优点:

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

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

  • 相关阅读:
    一月份反思内容:BUG & Communicate
    重构一个繁琐的数据结构
    GTD(Get Things Done)
    SortedList<TKey,TValue> 和 SortedDictionary<TKey,TValue>
    对Ado.net Entity Data Model Designer很失望
    A class to clone objects
    collection.All(x=> whatever(x)) 与 collection.Any(x=>whatever(x))
    Asp.net MVC里的TempData是一个整体
    Some tips about ubuntu server | or it may works on other linux distributions too
    每个程序员都必须遵守的编程原则
  • 原文地址:https://www.cnblogs.com/demiao/p/11449113.html
Copyright © 2011-2022 走看看