面向对象进阶(一)

一、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\n'% (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()

posted @ 2017-04-24 16:58  六神酱  阅读(145)  评论(0编辑  收藏  举报