面向对象进阶(一)
一、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())
六、setattr、delattr__和__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()