python笔记(21)--反射和高阶内置方法

内容目录:

  • 反射
  • 高阶内置方法

内容回顾:

  • 命名空间:类和对象分别存在不同的命名空间中

面向对象的三大特性:继承,多态,封装

  • 继承:
    • 单继承:(重要程度****)
      • 父类(超类,基类)
      • 子类(派生类):派生方法和派生属性
      • 子类的对象在调用方法和属性:先用自己的,没有才用父类的
    • 多继承:(面试会用到)
      • 不会超过三个父类,不要超过三层
      • 如果子类自己有就用自己的,如果没有就依次从左往后的顺序用父类的
      • 抽象类和接口类
      • 经典类和新式类:继承规则不同,深度优先和广度优先(面试****)
    • super 只能在python3中使用(面试会用到****)
      • super是根据mro广度优先顺序找上一个类
  • 多态:(面试会用到)
    • 多态和鸭子类型
  • 封装:(面试)
    • 私有的
    • __名字(双下划线变为私有属性)
    • 只能在类的内部调用,子类都无法继承
  • 三个装饰器
    • @property **** 规范,面试 #@name.stter
    • @staticmethod ***
    • @classmethod **** 当一个方法只使用了类的静态变量时,就给这个方法加上此装饰器,默认把self改为传cls参数,不能有其他参数

内容详细:

1.isinstance:判断对象和类的关系

#判断结果返回bool类型
class A:pass
class B(A):pass
a = A()
print(isinstance(a,A))	#True		isinstance(对象,类)

2.issubclass:判断子类和父类的关系

#判断结果返回bool类型
class A:pass
class B(A):pass
a = A()
print(issubclass(B,A))     #True	issubclass(子类,父类)

3.反射

  • 是用字符串类型的名字,去操作变量
  • 反射对象中的属性和方法:
    • hasattr
    • getattr
    • setattr
    • delattr

3.1 getattr(重要)

  • 反射对象的属性 ---getattr(对象,属性)

    class A:
        def func(self):
            print('in func')
    
    a = A()
    a.name = 'liyanan'
    a.age = 18
    # 反射对象的属性   --getattr(对象,属性)
    ret  = getattr(a,'name')    # 通过变量名的字符串形式取到的值
    print(ret)
    
    user = input('>>>>')
    print(getattr(a,user))  #假如输入name,则执行a.name
    
  • 反射对象的方法 ---getattr(对象,方法)

    #接上
    # 反射对象的方法
    ret = getattr(a,'func') #getattr(a,'func') == a.func
    ret()
    
  • 反射类的属性

    class A:
        price = 20
        def func(self):
            print('in func')
    
    # 反射类的属性
    # A.price
    print(getattr(A,'price'))
    
  • 反射类的方法

    class A:
        price = 20
        @classmethod
        def func(self):
            print('in func')
    
    # 反射类的方法:classmethod  staticmethod
    # A.func()
    if hasattr(A,'func'):           #判断类中是否存在第二个参数的方法
        getattr(A,'func')()         #如果有就执行
    
  • 反射模块的属性

    import my      # my为自己写的其他模块
    #反射模块的属性	my.day为模块的属性
    print(getattr(my,'day'))
    
  • 反射模块的方法

    #反射模块的方法
    getattr(my,'func')()
    
  • 内置模块也能用反射

  • 反射自己模块中的变量和函数

    import sys
    # print(sys.modules['__main__'])
    year = 2019
    def login():
        print('welcome')
    
    #反射自己模块中的变量
    print(getattr(sys.modules[__name__],'year'))
    user_in = input('>>>')
    print(getattr(sys.modules[__name__],user_in))
    
    #反射自己模块中的函数
    getattr(sys.modules[__name__],'login')()
    

3.2 hasattr

  • 与getattr配合使用,主要做判断

  • 注意参数要跟getattr保持一致

    import sys
    
    year = 2019
    
    if hasattr(sys.modules[__name__],'year'):
        print(getattr(sys.modules[__name__],'year'))
    

3.3 setattr(了解)

  • 设置修改变量

  • setattr(对象,'要修改的属性','修改的内容')

    class A:
        pass
    
    a = A()
    setattr(a,'name','nezha')
    setattr(A,'name','taibaijinxing')
    print(a.name)           #打印nezha
    print(A.name)           #打印taibaijinxing
    

3.4 delattr(了解)

  • 删除一个变量

    class A:
        pass
    
    a = A()
    setattr(a,'name','nezha')
    setattr(A,'name','taibaijinxing')
    
    delattr(a,'name')  
    print(a.name)   #打印taibaijinxing,因为实例化对象调用了父类的name属性
    delattr(A,'name')
    print(a.name)   #报错,没有name属性
    

4.高阶内置方法

  • __del__方法:析构函数:在删除一个对象之前,进行的一些收尾工作

    class A:
        def __del__(self):      #析构函数:在删除一个对象之前进行一些收尾工作
            self.f.close()
    
    a = A()
    a.f = open('db.txt','r',encoding='utf-8')   # 打开文件,拿到了文件操作句柄
    del a                       #del既执行了这个方法,又删除了变量
    
  • __call__方法:实例化后的对象加括号,相当于默认执行了此方法

    class A:
        def __init__(self,name):
            self.name = name
        def __call__(self, *args, **kwargs):
            for k in self.__dict__:
                print(k,self.__dict__[k])
    
    a = A('liyanan')()  #实例化对象后加括号相当于执行了内部的__call__方法
    #a()     结果为打印self.__dict__中的静态属性   name liyanan
    
  • item方法

    • getitem
    • setitem
    • delitem
    • 附加的delattr
    class Foo:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
        #getitem方法
        def __getitem__(self, item):
            if hasattr(self,item):          #判断item是否存在/传值
                return self.__dict__[item]
        #setitem方法
        def __setitem__(self, key, value):
            self.__dict__[key] = value
        #delitem方法
        def __delitem__(self, key):
            del self.__dict__[key]
        
        #delattr方法
        def __delattr__(self, item):
            print('del obj.key时,我执行')
            self.__dict__.pop(item)
            
    f = Foo('alec','18','男')
    print(f['name'])    #f['']这种格式默认执行了类中的__getitem__方法,等于f.name
    
    f['hobby'] = 'python'   #默认调用了setitem方法,使类中的字典添加了key和value
    print(f.hobby,f['hobby'])   #结果都为python
    
    del f.hobby         #先调用类中的delattr方法,如果没有就调用object中的(直接删除)
    del f['hobby']      #默认调用了delitem方法,删除了类中的静态属性
    
  • __new__用法(面试会考)

    • 所有的类中都是先执行__new__方法,再执行__init__方法

    • 使用场景:设计模式:单例模式:只能有一个实例化对象,后面实例化的对象属性都会覆盖第一个对象的属性,如果没有覆盖则用第一个对象的属性

      #单例模式
      class A:
          __instance = False					#设置一个私有属性
          def __init__(self,name,age):
              self.name = name
              self.age = age
          def __new__(cls, *args, **kw):		#先执行new,再执行__init__方法
              if cls.__instance:
                  return cls.__instance
              cls.__instance = object.__new__(cls)
              return cls.__instance
      
      yanan = A('yanan',26)
      yanan.cloth = 'cool'
      beijing = A('beijing',23)
      print(yanan)    #<__main__.A object at 0x000001B336D38C50>
      print(beijing)  #<__main__.A object at 0x000001B336D38C50> 一样的内存地址,证明只能实例化一个对象
      print(yanan.name)       #beijing	被第二次实例化对象<北京>给覆盖了
      print(beijing.name)     #beijing	
      print(beijing.cloth)    #cool		第二次实例化对象<北京>没有覆盖,则用第一个对象的属性
      
  • __eq__方法

    • 用法:比较实例化后的对象属性是否相等

      class A:
          def __init__(self,name):
              self.name = name
          #eq方法
          def __eq__(self, other):
              if self.__dict__ == other.__dict__:
                  return True
              else:
                  return False
      
      ob1 = A('pig')
      ob2 = A('pig')
      print(ob1 == ob2)   #True
      
  • __hash__方法

    • hash()是系统的哈希用法,以对象的内存地址进行哈希的

    • __hash__可以自己控制哈希用法

      class  A:
          def __init__(self,name,sex):
              self.name = name
              self.sex = sex
          def __hash__(self):
              return hash(self.name+self.sex)
      
      a = A('agg','公')
      b = A('agg','公')
      print(hash(a))
      print(hash(b))
      #系统的哈希用法是根据内存地址处理的
      #此类中的自己写的哈希算法是根据值来处理的
      
  • 示例:

    • 实例化对象去重

      class  A:
          def __init__(self,name,sex,age):
              self.name = name
              self.sex = sex
              self.age = age
          def __eq__(self, other):
              if self.name == other.name and self.sex == other.sex:
                  return True
              return False
      
          def __hash__(self):
              return hash(self.name + self.sex)
      
      a = A('agg','公',5)
      b = A('agg','公',5)
      print(hash(a))
      print(hash(b))
      print(set((a,b)))   #去重,去除重复的实例化对象(只去重name和sex)
      
posted @ 2020-05-22 18:06  薛定谔的猫儿  阅读(88)  评论(0编辑  收藏  举报