• 反射,内置方法,__str__ __repr__


    反射

    反射用到的mmp模块

    def wahaha():print('wahaha')
    
    class QQxing:
        def __init__(self,name):
            self.name = name
        def ADCa(self):
            print('in ADCa',self.name)
    
    # a
    # b
    # wahaha
    # QQxing
    # getattr('a')
    
    
    import sys
    
    print(sys.modules)
    print(sys.modules[__name__])
    print(getattr(sys.modules[__name__],'a'))
    print(getattr(sys.modules[__name__],'b'))
    getattr(sys.modules[__name__],'wahaha')()
    name1='aaa'
    name2='bbb'
    name3='ccc'
    inp=input('>>>')
    print(inp)
    class A:
        Name1 = 'aaa'
        Name2 = 'bbb'
        Name3 = 'ccc'
    
        def __init__(self,name):
            self.name=name
        def func(self):
            print('in func',self.name)

    图示帮助理解

    
    
    a1=A('ddd')#实例化了一个ddd
    a1.func()#调用了func函数  in func ddd
    print(a1.name)#打印函数中名字  ddd
    
    getattr(a1,'func')#'func'是字符串类型的变量名
    getattr(a1,'func')() #in func ddd  加上括号执行函数
    print(getattr(a1,'func'))#打印的是地址
    print(getattr(a1,'name'))#打印实例化后,a1对应的名字
    
    if hasattr(A,'Name1'):
        print(getattr(A,'Name1'))#和hasattr搭配使用  #Name1
    print(getattr(A,'Name2'))   #Name2
    print(getattr(A,'Name3'))   #Name3
    
    while True:
        inp=input('>>>')
        if hasattr(A,inp):
            print(inp)
    使用字符串数据类型的变量名来操作一个变量的值
    使用反射获取某个命名空间的值
    需要
    有一个变量指向这个命名空间的字符串数据类型的名字,
    再使用getattr获取值
    如果是变量,能直接获得结果
    如果是函数,只能拿到内存地址,加上括号就是执行
    使用类名反射:静态属性,类方法,静态方法
    使用对象名反射:对象属性,类中的普通方法
    使用模块名反射:变量,函数,类
    在自己所在的文件夹中反射全局变量:getattr(sys.modules[__name__],'要反射的名字')
    import mmp
    print(mmp.a)#直接使用模块,调用模块中的变量
    print(getattr(mmp,'a'))#使用反射,调用模块中的变量a
    mmp.wahaha()#直接使用模块调用模块中的函数
    getattr(mmp,'wahaha')()#使用反射调用模块中的函数
    
    print(mmp.QQxing)#直接使用模块,获取类的内存地址
    taibai=mmp.QQxing('太亮')#实例化模块中的类
    taibai.ADCa()#实例调用方法
    cls=getattr(mmp,'QQxing')#使用反射得到模块中类
    ret=cls('光头')#将得到的类实例化
    print(ret)#<mmp.QQxing object at 0x0000021FA2805D30>
    getattr(ret,'ADCa')()#in ADCa 光头 使用反射调用类中的方法
    hasattr ******
    getattr ******
    setattr ***
    delattr *
    import mmp
    class A:
        Name1='alex'
        Name2='taibai'
        Name3='egon'
        def __init__(self,name):
            self.name=name
        def func(self):
            print('in func,self.name')
    A.Country='中国'#
    A.Name1='alex_NB'#
    print(A.__dict__)#查看类下的内容
    setattr(A,'Country','印度')#将中国改为印度
    print(A.__dict__)#查看类下的内容
    
    setattr(A,'Role','Person')#增加一个静态属性  'Role'='Person'
    print(A.__dict__)#查看类下的内容
    delattr(A,'Name1')#删除Name1='alex'的静态变量
    print(A.__dict__)#查看类下的内容

    内置方法

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象
    issubclass(sub, super)检查sub类是否是 super 类的派生类
    a=10
    print(isinstance(a,int))#True
    
    class F:pass
    class Foo(F):pass
    obj=Foo()
    print(isinstance(obj,Foo))#True
    print(type(obj)is Foo)#True
    print(isinstance(obj,F))#True
    print(type(obj)is F)#False
    
    class F:pass
    class Foo(F):pass
    print(issubclass(Foo,F))#True
    print(issubclass(F,Foo))#False
    类的内置方法 双下方法 魔术方法
    对象加上(),可以调用这个类的__call__方法
    class Foo:
        def __call__(self):
            print('call')
    Foo()()#call
    obj=Foo()
    obj()#相当于调用__call__call
    内置函数的len函数是依赖类中的__len__
    class Classes:
        def __init__(self,student_lst):
            self.student_lst=student_lst
        def __len__(self):return len(self.student_lst)
    
    clas=Classes(['张三','李四','王五'])
    print(len(clas.student_lst))#不依赖__len__
    print(len(clas))#依赖__len__
    
    class Wahaha:
        def __init__(self,num,name,age):
            self.num=num
            self.name=name
            self.age=age
        def __len__(self):
            return len(self.__dict__)#返回类中属性的个数
    obj=Wahaha(6,'alex',8)
    print(len(obj.__dict__))#3
    print(len(obj))#3  依赖__len__
    __eq__  判断值是否相等的时候依赖__eq__的结果
    class QQxing:pass
        # def __eq__(self,other):本题中没有用到函数的内容(__eq__ 方法)
        #     if type(self)==type(other) and self.__dict__==other.__dict__:
        #         return True
        #     else:
        #        return False
    q1=QQxing()
    q1.name='alex'
    q2=QQxing()
    q2.name='egon'
    print(q1,q2)#两个内存地址不同
    print(q1==q2)# 两个自定义对象之间是否值相等,会根据内存地址去判断
    面试题 判断值是否相等的时候依赖__eq__的结果,==就是在内部调用了__eq__方法
    两个对象的名字和性别相同,那么这两个对象就是同一个人
    class Person:
        def __init__(self,name,sex,age):
            self.name=name
            self.sex=sex
            self.age=age
        def __eq__(self,other):
            if type(self)==type(other) and self.name==other.name and self.sex==other.sex :
                return True
            else:return False
    p1=Person('松松','',23)
    p2=Person('松松','',24)
    p3=Person('小灰灰','',23)
    print(p1==p2)#True
    print(p1==p3)#False
    print(p2==p3)#False
    
    hash() 在内存的优化上起到了作用
    dict,set
    两个对象的名字和性别相同,那么这两个对象就是同一个人,对10个对象进行去重
    class Person_lst:
        def __init__(self,name,sex,age):
            self.name=name
            self.sex=sex
            self.age=age
        def __hash__(self):
            return hash(self.name+self.sex)
        def __eq__(self,other):
            if type(self)==type(other) and self.name==other.name and self.sex==other.sex :
                return True
            else:return False
    l1=[('松松','',23),('松松','',24),('松松','',23),('灰灰','',23),('灰灰','',24),
        ('灰灰','',23),('张三','',23),('李四','',23),('王五','',23),('李六','',23),]
    # p1=Person_lst(l1)
    p1=[Person_lst(i[0],i[1],i[2],) for i in l1]
    p2=list(set(p1))
    print(p2)
    for i in p2:
        # print(i.__dict__)#以字典的形式打印出来,因为类的空间里就是以这种方式储存的。
        print(list(i.__dict__.values()))#将p2(类)空间中的内容打印出来。
    
    class Person_lst:#巧用内置方法
        def __init__(self,name,sex,age):
            self.name=name
            self.sex=sex
            self.age=age
        def __hash__(self):
            return hash(self.name+self.sex)
        def __eq__(self,other):
            if type(self)==type(other) and self.name==other.name and self.sex==other.sex :
                return True
            else:return False
        def __str__(self):  # 必须返回一个str数据类型
            return ','.join([self.name,self.sex,str(self.age)])
    l1=[('松松','',23),('松松','',24),('松松','',23),('灰灰','',23),('灰灰','',24),
        ('灰灰','',23),('张三','',23),('李四','',23),('王五','',23),('李六','',23),]
    # p1=Person_lst(l1)#不能直接传列表,__init__方法的三个参数传不进去
    p1=[Person_lst(i[0],i[1],i[2],) for i in l1]#一次性实例化10个对象
    p2=list(set(p1))#利用集合去重
    # print(p2)#打印的是地址
    for i in p2 :#将筛选过的打印出来
        print(i)
    print(hash(p1[0]))#2590952859388047099
    print(hash(p1[1]))#2590952859388047099
    print(hash(p1[2]))#9131494265893997627
    print(hash(p1[3]))#-5720704507138757199
    print(hash(p1[4]))#-5720704507138757199
    print(hash(p2[4]))#-8555849577569044973
    print(hash(p2[5]))#580991108371939176
    print(hash(p2[7]))#5769660943707885971
    p1第一个和第二个,第四个和第五个判定为同一个人,所以hash值相等
    p2中已经去重了,所以每个人的hash值不相等
    hash(obj1)==hash(obj2) and obj1.__eq__(obj2):是重复的
    obj1.__hash__()==obj2.__hash__() and obj1.__eq__(obj2):是重复的
    py 2.7
    class Person:
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    person_lst=[Person('egon',i,'male') for i in range(100)]
    for i in set(person_lst):
        print(list(i.__dict__.values()))

    __str__ __repr__

    l=[1,2,3]#实际是列表的实例化
    a='cba'
    # 语法糖
    print(a)
    print(1)
    class QQxing:pass
    q1=QQxing()
    print(q1)#内存地址
    
    
    class Course:
        def __init__(self,name,price,period):
            self.name=name
            self.price=price
            self.period=period
        def __str__(self):
            return '*'.join([self.name,str(self.price),self.period])#列表转字符串,用join
    python=Course('python',19800,'6month')
    linux=Course('linux',17800,'6month')
    for i in [python,linux]:
        print(i)#python*19800*6month    linux*17800*6month
    print(python)#没有__str__方法,打印出来的是内存地址
    print('course:%s' % python)#course:python*19800*6month
    print('a:',str(python))#a: python*19800*6month
    __str__方法和str(),print()  %s 都是息息相关的
    
    
    class Student:
        def __init__(self,name,sex,age):
            self.name=name
            self.sex=sex
            self.age=age
        def __repr__(self):
            return self.name
    stu1=Student('光头','',25)
    print('学生姓名:%r' % stu1)#学生姓名:光头
    print(repr(stu1))#光头
    __repr__方法 和repr() %r 都是息息相关的
    
    
    class Student:
        def __init__(self,name,sex,age):
            self.name=name
            self.sex=sex
            self.age=age
        # def __str__(self):
        #     return '&'.join([self.name,self.sex,str(self.age)])
        # def __repr__(self):
        #     return self.name
        def __repr__(self):
            return ''.join([self.name,self.sex,str(self.age)])
    stu1=Student('光头','',25)
    print('%s' % stu1)#光头:男:25
    print('学生:%r' % stu1)#学生:光头:男:25
    print(str(stu1))#光头:男:25
    print(repr(stu1))#光头:男:25
    在没有实现__str__方法的情况下,__repr__能够完全代替__str__的功能
    但是__str__不能代替__repr__的工作
    在__repr__和__str__都存在的情况下:
        __repr__方法 和repr() %r 都是息息相关的
        __str__方法和str() % r都是息息相关的
    *coding:utf_8*
    format_dict={
        'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
        'tna':'{obj.type}:{obj.name}:{obj.addr}',
        'tan':'{obj.type}*{obj.addr}*{obj.name}',
    }
    class School:
        def __init__(self,name,addr,type):
            self.name=name
            self.addr=addr
            self.type=type
        def __format__(self,format_spec):#format_spec='nat'
            if not format_spec or format_spec not in format_dict:
                format_spec='nat'
            fmt=format_dict[format_spec]#fmt='{obj.name}-{obj.addr}-{obj.type}'
            return fmt.format(obj=self)#'{obj.name}-{obj.addr}-{obj.type}'.format(obj=self) 格式化输出
    
    s1=School('清华','北京','公立')
    print(format(s1,'nat'))#清华-北京-公立
    print(format(s1,'tna'))#公立*清华1:北京
    print(format(s1,'tan'))#公立*北京*清华1
    print(format(s1,'iwejkwocoi'))#清华1-北京-公立
    
    
    class A:pass
    o=A()
    o.name='a'
    o.addr='b'
    o.type='c'
    print('{obj.name}-{obj.addr}-{obj.type}'.format(obj=o))#格式化输出
    总结:
    反射 —— 明显的简化代码
    能拿到的变量名本来就是一个字符串的时候
    用户输入的、文件读入的、网络上传输
    hasattr 判断某个变量在不在命名空间中
    getattr 获取某个名空间中的变量
    setattr 给空间中的某个变量赋值、或者创建变量
    delattr 从空间中删除某个变量
    ***所有的变量都是字符串数据类型的变量名
    
    
    内置方法
    内置方法,内置函数,内置的模块
    你自定义的类或者对象
    能否利用一些内置函数,内置模块实现功能
    你的内置方法是否实现了响应的功能
    hash()函数就依赖__hash__方法
    len()函数就依赖__len__方法
    ==函数就依赖__eq__方法
    format函数就依赖__format__方法
    str,print,%s函数就依赖__str__方法
    repr,%r函数就依赖__repr__方法
        * 在没有str的时候所有的引用__str__方法的
          地方都可以自动引用__repr__方法
    set 依赖 __hash__和__eq__方法来完成去重

    123

  • 相关阅读:
    ubuntu 14.04 (desktop amd 64) 下载
    ubuntu16.04 server(amd 64) 下载
    vim/vi中移动光标键会变成A,B,C,D的解决办法
    ubuntu 14.04(desktop amd 64) nginx 安装启动停止
    ubuntu-server14.04 网络配置
    selenium-chrome-headless
    selenium-firefox-headless
    哈希表-java
    冒泡排序-java
    wc的使用
  • 原文地址:https://www.cnblogs.com/daofaziran/p/9113884.html
Copyright © 2020-2023  润新知