python3--面向对象的进阶

发布时间:2018-04-18 20:10:56编辑:Run阅读(3375)

    昨日内容练习

    class A:
        def func1(self):pass  # func1 普通方法
        @classmethod
        def func2(self):pass  # func2 类方法
        @staticmethod
        def func3(self):pass  # func3 静态方法
    
    # func1 普通方法 对象和类绑定的过程
    a = A()
    b = A()
    print(A.func1)  # 3个地址都不一样
    print(a.func1)
    print(b.func1)
    
    # func2 类方法 由于不适用对象内存空间中的属性,
    # 所以不会将对象和方法绑在一起,而是将类和方法绑在一起
    print(A.func2)
    print(a.func2)  # 对象能找到类,类里面绑着方法
    print(b.func2)
    
    # func3 静态方法 不是绑定方法 没有和对象或者类发生任何绑定关系
    print(A.func3)
    print(a.func3)
    print(b.func3)

    执行结果

    1 普通方法,func1结果


    <bound method A.func1 of

    <bound method A.func1 of


    2 类方法,func2结果

    <bound method A.func2 of

    <bound method A.func2 of

    <bound method A.func2 of


    3 静态方法,func3结果





    isinstance(对象名,类名) 返回True,False

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

    例子

    class A:pass
    class B(A):pass
    b = B()
    print(isinstance(b, A))  # 能够检测到继承关系
    print(isinstance(b, B))
    print(type(b) is A)
    print(type(b) is B)  # type只单纯的判断类

    执行结果

    True

    True

    False

    True


    issubclass(子类名,父类名) 返回True,False

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

    例子,单继承

    class A:pass
    class B:pass
    class C(B):pass
    class D(C):pass
    print(issubclass(C,B))  # 判断C是不是B的子类
    print(issubclass(D,C))  # 判断D是不是C的子类
    print(issubclass(D,B))  # 判断D是不是C的子类
    print(issubclass(D,A))  # 判断D是不是A的子类

    执行结果

    True

    True

    True

    False


    例子2,多继承

    class A:pass
    class B:pass
    class C(A,B):pass
    class D(C):pass
    
    print(issubclass(C,A))  # 判断C是不是A的子类
    print(issubclass(C,B))  # 判断C是不是B的子类
    print(issubclass(D,B))  # 判断D是不是B的子类
    print(issubclass(D,A))  # 判断D是不是A的子类

    执行结果

    True

    True

    True

    True


    面向对象进阶(反射,非常重要的知识点*******7星)

    1 什么是反射

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问,检测和修改它本身状态或行为的一种能力(自省),它首先被程序语言的设计领域所采用,并在Lisp和面向对象取得了成绩


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

    四个可以实现自省的函数

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


    反射

    正常情况下如果可以拿到这个变量, 那么如有这个变量的字符串形式,就是用反射可以获取到这个值

    使用字符串数据类型的变量名 访问一个命名空间中的名字

    找一个属性,直接就可以找到这个属性的值

    找一个方法,找到的是这个方法的内存地址


    getattr 使用字符串数据类型的变量名 访问一个命名空间中的名字

    源代码

    def getattr(object, name, default=None): # known special case of getattr
        """
        getattr(object, name[, default]) -> value
        
        Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
        When a default argument is given, it is returned when the attribute doesn't
        exist; without it, an exception is raised in that case.
        """
        pass


    例子

    class A:
        role = 'person'  # 静态属性
        def func(self):
            print('*'*10)
    print(A.__dict__['role'])  # 查看静态属性的值
    ret = input('>>>')  # 用户输入role
    print(A.__dict__[ret])  # 实际上就是执行了最上面的print

    执行结果

    person

    >>>role

    person


    那么如何让用户输入func然后去执行类里面的方法func呢?

    class A:
        role = 'person'  # 静态属性
        def func(self):
            print('*'*10)
    ret = input('>>>')  # 用户输入func
    # 这里要用到字符串拼接+eval函数才能实现
    s = 'A'
    ss = s + '.' + ret
    eval(ss)(1)

    执行结果

    >>>func

    **********


    这样很麻烦,也不安全,还有什么方法呢?

    getattr()  从命名空间中获取这个名字对应的值

    class A:
        role = 'person'  # 静态属性
        def func(self):
            print('*'*10)
    
    # 从A的命名空间里找一个属性,直接就可以找到这个属性的值
    # 通俗点就是需要获取谁(func),就是getattr(A,'func') getattr(类,'属性名')
    print(getattr(A, 'role'))
    
    a = A()  # 实例化一个对象a
    # 从A的命名空间里面找一个方法,找到的是这个方法的内存地址,如果要执行这个方法,在后面加()
    print(getattr(a, 'func'))
    getattr(a, 'func')()
    
    #getattr如何让用户输入一个类中的方法名,并执行
    ret = input('>>>:')
    getattr(a, ret)()  # getattr(a, ret)实际上获取的就是func方法的内存地址,后面加()就表示执行

    执行结果

    person

    <bound method A.func of

    **********

    >>>:func

    **********


    例2

    class A:
        role = 'Person'
        def __init__(self):
            self.money = 500
        def func(self):
            print('*'*10)
    a = A()
    print(a.func)  # 打印a.func的内存地址
    getattr(a, 'func')()  # 使用getattr获取名字对应的值,名字加()就表示执行这个方法
    print(getattr(a, 'money'))  # 使用getattr获取名字对应的值

    执行结果

    <bound method A.func of

    **********

    500



    hasattr() 判断一个命名空间中有没有这个名字

    源码

    def hasattr(*args, **kwargs): # real signature unknown
        """
        Return whether the object has an attribute with the given name.
        
        This is done by calling getattr(obj, name) and catching AttributeError.
        """
        pass


    例1

    class A:
        role = 'person'
        def func(self):
            print('py3study.com')
    
    a = A()
    print(hasattr(a, 'r'))  # 也可以写成 print(hasattr(A, 'r'))
    print(hasattr(a, 'role'))
    print(hasattr(a, 'func'))

    执行结果

    False

    True

    True


    hasattr()经常与getattr()一起用,首先判断一个命名空间中有没有这个名字,有的话就用getattr获取这个名字对应的值

    示例

    class A:
        role = 'person'
        def func(self):
            print('py3study.com')
    
    ret = input('>>>')
    if hasattr(A, ret):  # 判断是否存在
        print(getattr(A, ret))  # 如果存在则打印内存地址
    if hasattr(A, ret):
        func = getattr(A, ret)  # 如果存在则执行这个方法
        func(1)
    else:
        print('error')  # 不存在则报错

    执行结果

    >>>func


    py3study.com


    类使用类命名空间中的名字

    对象使用对象能用的方法和属性

    模块使用模块中的名字

    导入os模块,利用getattr获取os模块中'rename'对应的值,os.rename('old','new')执行改文件名的操作

    import os;getattr(os, 'rename')('user', 'user_info') 


    导入time模块,利用getattr获取time模块中'time'对应的值,print(time.time())打印时间戳

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


    从自己所在的模块中使用自己名字

    示例

    def login():
        print('执行login功能')
    
    def  register():
        print('执行register功能')
    
    import sys
    print(sys.modules['__main__'])  # 打印当前文件的路径,一个.py文件就相当于一个模块
    func = input('>>>')
    if hasattr(sys.modules['__main__'], func):  # 判断当前模块中的命名空间,是否有用户输入的这个名字
        getattr(sys.modules['__main__'], func)()  # 存在的话执行用户输入的名字加()这个函数

    执行结果

    >>>login

    执行login功能


    类使用类命名空间中的名字

    getattr(类名,'名字')

    对象使用对象能用的方法和属性

    getattr(对象名,'名字')

    模块使用模块中的名字

    导入模块

    getattr(模块名,'名字')

    从自己所在的模块中使用自己名字

    import sys

    getattr(sys.modules['__main__'],名字)

    getattr一定要和hasattr配合使用


    反射 :4个内置函数

    getattr  # 从命名空间中获取这个名字对应的值

    hasattr  # 判断一个命名空间中有没有这个名字  

    setattr  # 修改和新建

    delattr  # 删除一个属性


    setattr,delattr

    setattr源码

    def setattr(x, y, v): # real signature unknown; restored from __doc__
        """
        Sets the named attribute on the given object to the specified value.
        
        setattr(x, 'y', v) is equivalent to ``x.y = v''
        """
        pass

    delattr源码

    def delattr(x, y): # real signature unknown; restored from __doc__
        """
        Deletes the named attribute from the given object.
        
        delattr(x, 'y') is equivalent to ``del x.y''
        """
        pass



    增删改 对象属性

    class A:
        def __init__(self, name):
            self.name = name
    
        def wahaha(self):
            print('噢噢噢噢哦哦哦')
    a = A('Sam')
    print(a.name)
    a.wahaha()
    print(a.__dict__)
    
    # 使用setattr: 无则增加有则修改的原则
    setattr(a, 'age', 18)  # 给a对象新增一个属性
    print(a.__dict__)
    a.wahaha()  # 执行wahaha()方法
    
    # 使用setattr: 无则增加有则修改的原则
    setattr(a, 'name', 'Jack')  # 修改a对象的name属性为Jack
    print(a.__dict__)
    
    del a.name  # 删除a对象的name属性
    print(a.__dict__)
    
    # 使用delattr删除
    delattr(a, 'age')
    print(a.__dict__)

    执行结果

    Sam

    噢噢噢噢哦哦哦

    {'name': 'Sam'}

    {'name': 'Sam', 'age': 18}

    噢噢噢噢哦哦哦

    {'name': 'Jack', 'age': 18}

    {'age': 18}

    {}


    例2

    class A:
        def __init__(self, name):
            self.name = name
    
        def  wahaha(self):
            print('aaaaaaaaaaa')
    
    def qqxing(self):
        print('qqqqqqqqq')
    
    a = A('Tom')
    setattr(a, 'qqxing', qqxing)  # setattr把函数qqxing 加到类里面去了
    a.qqxing(a)
    
    # 使用getattr函数从命名空间中获取这个名字对应的值
    getattr(a, 'qqxing')(a)

    执行结果

    qqqqqqqqq

    qqqqqqqqq


关键字