zoukankan      html  css  js  c++  java
  • 第十一章 面向对象进阶

    1.反射                                                        

    1.什么叫反射

    反射就是通过字符串数据类型的变量名来访问变量的值

    像x.y这样的形式,都可以用反射

    # 例:
    print('aaa'.startswith)
    # <built-in method startswith of str object at 0x000001D949B6B500>
    ret = getattr('aaa', 'startswith')
    print(ret)
    # <built-in method startswith of str object at 0x000001D949B6B500>
    
    # 执行
    print('aaa'.startswith('a'))
    # True
    print(ret('a'))
    # True

    2.反射的类型

      对象名 反射 对象属性 和 方法

      类名 反射 静态属性

      模块 反射 模块中的名字

      反射 对自己所在文件中的名字

    1) 对象名 反射 方法

    # 对象名 反射 方法
    class Person:
        def eat(self):print('eating')
        def drink(self):print('drinking')
        def play(self):print('playing')
        def sleep(self):print('sleepping')
    
    alex = Person()
    while True:
        inp = input('>>> ')
        # if hasattr(alex, inp):
        getattr(alex, inp)()
    
    # >>> eat
    # eating
    # >>> drink
    # drinking
    # >>> play
    # playing
    # >>> sleep
    # sleepping
    # >>> eatt
    #     getattr(alex, inp)()
    # AttributeError: 'Person' object has no attribute 'eatt'

    说明

    1. 首先 使用getattr取获取一个名字,如果在这个对象的命名空间中没有这个名字,会报错
    2. 这时候就引入了getattr的反射好伴侣hasattr
    3. 如果使用getattr去获取一个方法,那么只能拿到这个方法的内存地址
    4. 加上括号就是执行,当然,括号里的参数可以照传不误
    5. 如果获取getattr获取一个属性,那么直接使用反射就可以获取到值

    引入hasattr,判断对象是否含有这个方法

    # 引入了getattr的反射好伴侣hasattr,判断对象是否含有这个方法
    class Person:
        def eat(self):print('eating')
        def drink(self):print('drinking')
        def play(self):print('playing')
        def sleep(self):print('sleepping')
    
    alex = Person()
    while True:
        inp = input('>>> ')
        if hasattr(alex, inp):
            getattr(alex, inp)()
    # >>> eat
    # eating
    # >>> eatt

    2) 对象名 反射 对象属性

    class Person:
        def __init__(self,name):
            self.name = name
        def eat(self):print('eating')
        def drink(self):print('drinking')
        def play(self):print('playing')
        def sleep(self):print('sleepping')
    
    alex = Person('alex')
    print(getattr(alex, 'name'))
    # alex

    3) 类名 反射 静态属性

    class Person:
        role = '静态属性'
    
    print(getattr(Person, 'role'))
    # 静态属性

    4) 模块 反射 模块中的名字

    '''
    mo.py文件
    money = 100
    def func1():
        print('in func1')
    
    class Manager:
        def eat(self):
            print('eating')
    '''
    
    import mo
    import time
    print(mo.money)
    # 100
    # 反射模块中的变量
    print(getattr(mo, 'money'))
    # 100
    mo.func1()
    # in func1
    # 括号内接参数
    getattr(time, 'sleep')(0.5)
    # 反射模块中的函数名
    getattr(mo, 'func1')()
    # in func1
    
    # 反射模块中的类名
    Manager = getattr(mo, 'Manager')
    print(Manager)
    # <class 'mo.Manager'>
    a = Manager()
    a.eat()
    # eating

    5) 反射自己所在文件中的名字

    # 思路:找自己的文件名
    value = '123'
    import sys
    print(sys.modules['__main__'])
    print(getattr(sys.modules['__main__'], 'value'))

    2.isinstance和issubclass                                     

    # isinstance()
    class Foo:
        pass
    
    obj = Foo()
    print(isinstance(obj, Foo))
    # True
    # 说明:isinstance(obj, cls) 检查obj是否是类的对象
    
    # issubclass()
    class Foo:
        pass
    
    class Son(Foo):
        pass
    
    print(issubclass(Son, Foo))
    # True
    # 说明:issubclass(Son, Foo) 检查Son类是否是Foo类的子类

    3.__new__                                                    

    # __new__   构造方法、创建一个对象
    # __init__  初始化方法
    
    class Foo:
        def __new__(cls, *args, **kwargs): #self还没有创建
            print('执行我啦')
            return object.__new__(cls) #-->self
        def __init__(self):
            print('2222222')
    
    Foo()
    # 执行我啦
    # 2222222
    
    # 说明:先执行new方法,object.__new__
    # 再执行__init__
    # #
    # Foo() --> python解释器接收到你的python代码
    # python解释器替你去做了很多操作
    # 包括 主动帮助你 调用 new方法 去创造一个对象 -- 开辟内存空间 -- python语言封装了开辟内存的工作
    # object的new方法里 -- 帮你创造了对象
    # 调用init的用到的self参数,就是new帮你创造的对象

    单例模式

    # 什么叫单例模式
    # 单例模式 : 某一类 只有一个实例
    
    class Person:
        __isinstance = None
        def __new__(cls, *args, **kwargs):
            if not cls.__isinstance :
                obj = object.__new__(cls)
                cls.__isinstance = obj
            return cls.__isinstance
        def __init__(self,name):
            self.name = name
    
    alex = Person('alex')
    alex.age = 18
    egon = Person('egon')
    print(egon.age)
    # 18
    print(id(alex))
    # 2550191724752
    print(id(egon))
    # 2550191724752
    print(alex.name)
    # egon
    print(egon.name)
    # egon
    
    # __new__生孩子
    # 类 : 生一个小孩__new__ 给这个小孩穿衣服 __init__
    # 单例模式下的类 : 只有一个小孩,只有内部的属性变了,孩子没变
    
    

    4.__len__                                                    

    class A:
        def __len__(self):
            return 10
    
    a = A()
    print(len(a))
    # 10
    class A:
        pass
    a = A()
    print(len(a))
        # print(len(a))
    # TypeError: object of type 'A' has no len()

    5.__str__和__repr__                                          

    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 __repr__(self):
            return 'School(%s,%s)' %(self.name,self.addr)
        # def __str__(self):
        #     return '(%s,%s)' %(self.name,self.addr)
    
        def __format__(self, format_spec):
            # if format_spec
            if not format_spec or format_spec not in format_dict:
                format_spec='nat'
            fmt=format_dict[format_spec]
            return fmt.format(obj=self)
    
    # 1- 改变对象的字符串显示__str__,__repr__
    s1=School('oldboy1','北京','私立')
    print('from repr: ',repr(s1))
    # from repr:  School(oldboy1,北京)
    print('from str: ',str(s1))
    # from str:  (oldboy1,北京)
    print(s1)
    # (oldboy1,北京)
    # 将__str__注释后的结果为__repr__的格式化结果
    # School(oldboy1,北京)
    
    # 说明:str函数或者print函数--->obj.__str__()
    # repr或者交互式解释器--->obj.__repr__()
    # 如果__str__没有被定义,那么就会使用__repr__来代替输出
    # 注意:这俩方法的返回值必须是字符串,否则抛出异常
    
    # 2- format自定义格式化字符串
    print(format(s1,'nat'))
    # oldboy1-北京-私立
    print(format(s1,'tna'))
    # 私立:oldboy1:北京
    print(format(s1,'tan'))
    # 私立/北京/oldboy1
    print(format(s1,'asfdasdffd'))
    # oldboy1-北京-私立

    %s和%r

    class B:
    
        def __str__(self):
            return 'str : class B'
    
        def __repr__(self):
            return 'repr : class B'
    
    
    b = B()
    print('%s' % b)
    # str : class B
    print('%r' % b)
    # repr : class B

    6.其他方法                                                   

    class Person:
        def __init__(self,name):
            self.name = name
        def __str__(self):
            return 'a object of Person named %s'%self.name
        def __hash__(self):
            return 1231212
        def __len__(self):
            return 10
    a = Person('alex')
    b = Person('egon')
    # print(len(a))
    # print(hash(a))
    print(a)
    # a object of Person named alex
    print(b)
    # a object of Person named egon
    print(len(a))
    # 10
    print(hash(a))
    # 1231212
    print(len(b))
    # 10
    print(hash(b))
    # 1231212
    # 说明:类中的内置方法很多都和内置函数相关
    
    
  • 相关阅读:
    [转]项目需求范围管理
    JavaScript 王者归来
    [转]大文件上传组件
    [转]使用vs2005自带的sql2005 express
    JS判断Caps Lock
    [转]Web项目管理思考
    [转]JS严格验证身份证
    两分钟用C#搭建IE BHO勾子, 窃取密码
    asp.net性能提升十个方法(Microsoft)
    [转]Asp.net 将js文件打包进dll 方法
  • 原文地址:https://www.cnblogs.com/gongniue/p/9071744.html
Copyright © 2011-2022 走看看