zoukankan      html  css  js  c++  java
  • 面向对象进阶

    isinstance和issubclass

    isinstance(object, classinfo)检查是否obj是否是类 cls 的对象

    isinstance(object, classinfo)
    如果参数object是classinfo的实例,或者object是classinfo类的子类的一个实例, 返回True。如果object不是一个给定类型的的对象, 则返回结果总是False。
    如果classinfo不表示一个类(类型对象), 那么它要么是一个类的元组, 或者递归地包含这样的(由数据类型构成的)元组.其他的序列类型是不被允许的。
    class Foo(object):
    pass

    obj = Foo()
    print(isinstance(obj,Foo))

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

    class Foo(object):
        pass
     
    class Bar(Foo):
        pass
     
    issubclass(Bar, Foo)

    反射:是用字符串类型的名字去操作变量

    反射 就没有安全问题

    1 什么是反射

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

    2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

    四个可以实现自省的函数

    下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

    反射对象中的属性和方法  hasattr getattr setattr delattr

    class A:
        def func(self):
            print('in func')
    
    a = A()
    a.name = 'alex'
    a.age = 63

    反射对象的属性

    ret = getattr(a,'name')    #getattr(a,'name')=a.name   # 通过变量名的字符串形式取到的值

    print(ret)
    print(a.__dict__)    #把属性和值按键值对的形式存放在字典内

    '''
    {'name': 'alex', 'age': 63}
    '''
    变量名 = input('>>>')   # func   #输入属性来取值
    print(getattr(a,变量名))   
    print(a.__dict__[变量名])   #a.__dict__实际上是一个字典,按照键来取值

    反射对象的方法  就是让函数执行

    a.func()
    ret = getattr(a,'func')  #getattr(a,'func')=a.func
    ret()

    反射类的属性

    class A:
        price = 20
    
    A.price
    print(getattr(A,'price'))  #getattr(A,'price')=A.price
    class Foo:
        f = '类的静态变量'
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def say_hi(self):
            print('hi,%s'%self.name)
    
    obj=Foo('egon',73)
    
    #检测是否含有某属性
    print(hasattr(obj,'name'))
    print(hasattr(obj,'say_hi'))
    
    #获取属性
    n=getattr(obj,'name')
    print(n)
    func=getattr(obj,'say_hi')
    func()
    
    print(getattr(obj,'aaaaaaaa','不存在啊')) #报错
    
    #设置属性
    setattr(obj,'sb',True)
    setattr(obj,'show_name',lambda self:self.name+'sb')
    print(obj.__dict__)
    print(obj.show_name(obj))
    
    #删除属性
    delattr(obj,'age')
    delattr(obj,'show_name')
    delattr(obj,'show_name111')#不存在,则报错
    
    print(obj.__dict__)
    四个方法的演示

    反射类的方法 :classmethod staticmethod

    class A:
        price = 20
        @classmethod
        def func(cls):
            print('in func')
    
    A.func()
    if hasattr(A,'func'):   #查找A。func存在不,不存在就报错
        getattr(A,'func')()  #getattr(A,'func')=A.func
    模块

    反射模块的属性

    import  my_module
    print(my_module.day)#模块名.属性名
    print(getattr(my_module,'day'))

     反射模块的方法

    getattr(my_module,'read1')()

    内置模块也能用

    import time
    print(getattr(time,'time')())
    print(getattr(time,'asctime')())

     反射自己模块中的变量

    import sys
    year = 2018
    print(sys.modules['__main__'].year)
    print(getattr(sys.modules['__main__'],'year'))

    反射自己模块中的函数

    import sys
    def qqxing():
        print('qqxinng')
    
    sys.modules['__main__'].qqxing()
    getattr(sys.modules['__main__'],'qqxing')()

    变量名 = input('>>>')
    getattr(sys.modules['__main__'],变量名)()

    要反射的函数有参数怎么办?

    import time
    print(time.strftime('%Y-%m-%d %H:%M:%S'))
    print(getattr(time,'strftime')('%Y-%m-%d %H:%M:%S'))

    一个模块中的类能不能反射到?

    #in my_module.py
    class A:
        print('nihao')
    
    #in my.py
    import my_module
    print(getattr(my_module,'A')())

    setattr  修改设置属性

    class A:
        name = '222'
        def __init__(self,name):
            self.name = name
    a = A('111')
    print(A.name) print(a.name) setattr(a,'name','nezha') setattr(A,'name','alex') print(A.name) print(a.name) print(A.__dict__) print(a.__dict__)

     delattr #删除一个变量

    class A:
        name = '222'
        def __init__(self,name):
            self.name = name
    a = A('111')
    print(A.name)
    print(a.name)
    setattr(a,'name','nezha')
    setattr(A,'name','alex')
    print(A.name)
    print(a.name)
    
    delattr #删除一个变量
    delattr(a,'name')
    print(a.name)
    delattr(A,'name')
    print(a.name)

     内置的类方法

    内置的类方法和内置的函数有着千丝万缕出的联系

    双下方法

    __str__和__repr__

    改变对象的字符串显示__str__,__repr__

    自定制格式化字符串__format__

    object  里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址
    l = [1,2,3,4,5]   # 实例化 实例化了一个列表类的对象
    print(l)
    %s str()  直接打印 实际上都是走的__str__
    %r repr()  实际上都是走的__repr__
    repr 是str的备胎,但str不能做repr的备胎
    
    print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串
    如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
    repr(),只会找__repr__,如果没有找父类的
    #_*_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 __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)
    
    s1=School('oldboy1','北京','私立')
    print('from repr: ',repr(s1))
    print('from str: ',str(s1))
    print(s1)
    
    '''
    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常
    '''
    print(format(s1,'nat'))
    print(format(s1,'tna'))
    print(format(s1,'tan'))
    print(format(s1,'asfdasdffd'))
    
    class B:
    
         def __str__(self):
             return 'str : class B'
    
         def __repr__(self):
             return 'repr : class B'
    
    
    b=B()
    print('%s'%b)
    print('%r'%b)

    __del__

    析构方法,当对象在内存中被释放时,自动触发执行。

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

    __del__
    class A:
        def __del__(self):   # 析构函数: 在删除一个对象之前进行一些收尾工作
            self.f.close()
    a = A()
    a.f = open()   # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中
    del a          # a.f 拿到了文件操作符消失在了内存中
    del a   # del 既执行了这个方法,又删除了变量
    引用计数
    class Foo:
    
        def __del__(self):
            print('执行我了!')
    
    f1 = Foo()
    del f1
    print('----->')

    __call__

    对象后面加括号,触发执行。

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

    class A:
        def __init__(self,name):
            self.name = name
        def __call__(self):
            '''
                    打印这个对象中的所有属性
                    :return:
                    '''
            for k in self.__dict__:
                print(k,self.__dict__[k])
    a = A('alex')()
    class Foo:
    
        def __init__(self):
            pass
        
        def __call__(self, *args, **kwargs):
    
            print('__call__')
    
    
    obj = Foo() # 执行 __init__
    obj()       # 执行 __call__

    item系列

    __getitem__\__setitem__\__delitem__

    class Foo:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def __getitem__(self, item):    #通过双下划方法可以不用通过print(f.name)来取值,用print(f['name'])类似字典的方式取值
            if hasattr(self,item):
                return self.__dict__[item]
    
        def __setitem__(self, key, value):   #设置修改属性,有就覆盖,没有就添加
            self.__dict__[key] = value
    
        def __delitem__(self, key):    #删除属性
            del self.__dict__[key]
    
    f = Foo('egon',38,'')
    print(f['name'])
    f['hobby'] = ''
    print(f.hobby,f['hobby'])
    del f.hobby      # object 原生支持  __delattr__
    del f['hobby']   # 通过自己实现的
    print(f.__dict__)
    class Foo:
        def __init__(self,name):
            self.name=name
    
        def __getitem__(self, item):
            print(self.__dict__[item])
    
        def __setitem__(self, key, value):
            self.__dict__[key]=value
        def __delitem__(self, key):
            print('del obj[key]时,我执行')
            self.__dict__.pop(key)
        def __delattr__(self, item):
            print('del obj.key时,我执行')
            self.__dict__.pop(item)
    
    f1=Foo('sb')
    f1['age']=18
    f1['age1']=19
    del f1.age1
    del f1['age']
    f1['name']='alex'
    print(f1.__dict__)

    __new__

    __init__ 初始化方法
    __new__  构造方法 : 创建一个对象
    class A:
        def __init__(self):
            self.x = 1
            print('in init function')
        def __new__(cls, *args, **kwargs):
            print('in new function')
            return object.__new__(A, *args, **kwargs)
    
    a1 = A()
    a2 = A()
    a3 = A()
    print(a1)
    print(a2)
    print(a3)
    print(a.x)
  • 相关阅读:
    xfire webServeic 例子
    Spring3 url匹配规则
    js 字符串转化成数字
    JS回车事件,兼容目前所有浏览器
    笔记:Zygote和SystemServer进程启动过程
    安卓Task和Back Stack
    札记:Property动画
    札记:翻译-使用Scene和Transition实现【场景切换】动画效果
    算法:排序
    [BOT]自定义ViewPagerStripIndicator
  • 原文地址:https://www.cnblogs.com/aaronthon/p/8327913.html
Copyright © 2011-2022 走看看