• 面向对象进阶(一)


    一、isinstance和issubclass
    二、反射:getattr、setattr、delattr和hasattr
    三、模块间的反射
    四、反射的应用:可插拔机制
    五、字符串调用模块
    六、内置attr:_setattr_、_delattr__和__getattr_
    七、自定义数据类型:继承
    八、自定义数据类型:授权

    一、isinstance和issubclass

    isinstance(obj,class) #判断obj是否是class的对象
    issubclass(cls,calssinfo) #判断cls是否是calssinfo的子类

    二、反射

    通过传入的字符串寻找类内部属性key,应用到__dict__,其中key,value对应。

    class People:
        country = 'China'
        def __init__(self, str):
            self.str = str
        def walk(self):
            print('123')
    p = People('egon')
    

    2.1 hasattr

    hasattr(o,name) #返回bool值,确定name是否在对象o中(等同于name in o.dict)。

    print(hasattr(p, 'str'))
    print(hasattr(p, 'walk'))
    

    2.2 getattr

    getattr(o,name,defualt) #返回对象o的值,name是函数返回函数内存地址,加括号可以直接执行(等同于o.name)。
    如果name不再__dict__中,显示defualt。

    # print(getattr(p, 'country'))
    # a = getattr(p, 'walk')
    # a()
    

    一般hasattr与getattr配合使用:

    if hasattr(p, 'walf'):
        func = getattr(p,'walk')
        func()
    

    2.3 setattr

    setattr(object, name, value) #用于新增加对象object属性(等同与object.name = value)

    setattr(p, 'age', 19)
    

    2.4 delattr

    delattr(o, name) #删除对象属性(等同于del o.name)

    delattr(p,'str')
    

    三、反射当前模块的属性

    模块,既一个.py文件,一个模块可以作为一个对象,从而使用hasattr、getattr、setattr和delattr方法调用对象属性。

    import sys
    
    x = 111
    
    class Foo:
        pass
    
    def s1():
        print('s1')
    
    def s2():
        print('s2')
    
    this_module = sys.modules[__name__]
    print(this_module)
    print(hasattr(this_module, 'Foo'))
    print(getattr(this_module, 's1'))
    

    sys.modules[name] #用于获取当前模块作为对象

    四、反射的应用

    4.1 应用一

    import sys
    
    def add():
        print('add')
    
    
    def change():
        print('change')
    
    def search():
        print('search')
    
    this_module = sys.modules[__name__]
    
    while True:
        cmd = input('>>:').strip()
        if not cmd:continue
        if hasattr(this_module, cmd):
            func = getattr(this_module, cmd)
            func()
    

    4.2 应用二:可插拔机制

    可插拔机制,用于把协同工作时,调用其他模块代码时,其他模块代码未完成的情况下,不影响本地开发工作。
    FtpClient.py

    class FtpClient:
        def __init__(self, addr):
            print('正在连接服务器[%s]'% addr)
            self.addr = addr
    

    FtpHost.py

    import FtpClient      
                              
    f1 = FtpClient.FtpClient(
    if hasattr(f1, 'get'):   
        func_get = getattr(f1
        func_get()           
    else:                    
        print('不存在此方法。。。')   
    

    五、字符串调用模块

    # m = input('请输入你要倒入的模块:')
    #
    # m1 = __import__(m)
    # print(m1)
    # print(m1.time())
    
    import importlib
    t = importlib.import_module('time')
    print(t)
    print(t.time())
    

    六、setattrdelattr__和__getattr

    6.1__setattr__

    可以设置类内部属性

    class Foo:
        def __init__(self, name):
            self.name = name
    
        def __setattr__(self, key, value):
            if not isinstance(value, str):
                raise TypeError('must be str')
            self.__dict__[key] = value
    
    f1 = Foo('egon')
    f1.age = '10'
    print(f1.__dict__)
    

    6.2__delattr__

    删除类内部属性

    class Foo:
        def __init__(self, name):
            self.name = name
    
        def __delattr__(self, item):
            self.__dict__.pop(item)
    
    f1 = Foo('egon')
    del f1.name
    print(f1.__dict__)
    

    6.3__getattr__

    当对象调用的属性不存在时,返回None

    class Foo:
        def __init__(self, name):
            self.name = name
    
        def __getattr__(self, item):
            print('from getattr:%s'%item)
    
    f1 = Foo('egon')
    print(f1.xxx)
    

    七、基于继承的原理,实现自定义数据类型

    通过继承python内置类,重写类内部函数,增加函数功能。实现自定义效果。

    class List(list):
        def insert(self, index, object):
            if not isinstance(object, int):
                raise TypeError('must be int')
            super().insert(index, object)
    
        def append(self, object):
            if not isinstance(object, str):
                raise TypeError('must be str')
            super().append(object)
    
    l = List([1,3,5])
    
    l.insert(0, 90)
    print(l)
    
    l.append('80')
    print(l)
    

    八、授权

    有些内部函数例如open,并不是类,无法通过继承实现数据类型自定义,所以可以通过授权方式实现自定义。

    
    import time
    
    class Open:
        def __init__(self, file_path, mode = 'r', encoding = 'utf8'):
            self.f = open(file_path, mode=mode, encoding = encoding)
    
        def write(self, line):
            t = time.strftime('%Y-%m-%d %T')
            self.f.write('%s %s
    '% (t,line))
    
        def __getattr__(self, item):
            res = getattr(self.f, item)
            return res
    
    f1 = Open('a.txt','w+')
    f1.write('日志1')
    f1.write('日志2')
    f1.write('日志3')
    f1.write('日志4')
    
    
    print(f1.read())
    f1.seek(0)
    print(f1.read())
    f1.close()
    
    
  • 相关阅读:
    偶遇this之坑
    程序员的职业素养——读后感
    我怎么没想到——读后感
    黑客与画家——读后感
    漫谈认证与授权
    动手造轮子:实现一个简单的依赖注入(二) --- 服务注册优化
    动手造轮子:实现简单的 EventQueue
    asp.net core 自定义 Policy 替换 AllowAnonymous 的行为
    SQL Server 中 `JSON_MODIFY` 的使用
    WeihanLi.Npoi 近期更新
  • 原文地址:https://www.cnblogs.com/sunqim16/p/6757756.html
Copyright © 2020-2023  润新知