isinstance和type区别
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。
例如:
class A:
pass
class B(A):
pass
print(isinstance(A(),A)) #True
print(type(A()) == A) #True
print(isinstance(B(),A)) #True
print(type(B()) == A) #False
如果要判断两个类型是否相同推荐使用 isinstance()
issubclass() 方法用于判断参数 class 是否是类型参数 classinfo 的子类
issubclass(class, classinfo)
反射
通过字符串的形式操作对象的相关属性,python中的一切事物皆对象(都可以使用反射)
hasattr(obj,'name') ---->obj.name
getattr(obj,'name',default='错误') ---->obj.name (如果没找到就返回default的值)
setattr(obj,'name',name) ---->obj.name = name
delattr(obj,'name') ---->del obj.name
python一切皆对象,类和模块也可以使用反射
import sys
obj = sys.modules[__name__] #获取当前模块名
class BlackMedium:
def __init__(self,name,addr):
self.name = name
self.addr = addr
def rent_house(self):
print('[%s] 正在租房子'.format(self.name))
b1 = BlackMedium('万成置地','天露园')
#b1.name---->b1.__dic__['name']
print(b1.__dict__)
print(hasattr(b1,'name'))
print(hasattr(b1,'haha')) #没有返回False
print(getattr(b1,'name'))
print(getattr(b1,'rent_house'))
func = getattr(b1,'rent_house')
func()
#自定义default
print(getattr(b1,'nameaa','没有该属性'))
#修改,没有则添加(可以作用在函数)
setattr(b1,'haha','F')
setattr(b1,'name','A')
setattr(b1,'func',lambda x:x+1)
setattr(b1,'func2',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.func(10))
print(b1.func2(b1))
#删除
delattr(b1,'name')
print(b1.__dict__)
类的内置attr属性(实例用的才会触发)
class Foo:
x = 1
def __init__(self,y):
self.y = y
#属性不存在时会自动触发 __getattr__
def __getattr__(self, item):
print('你找的属性 [%s] 不存在'%item)
#删除属性时会触发 __delattr__
# def __delattr__(self, item):
# # del self.item #无限递归
# self.__dict__.pop(item)
#
# #设置属性时会触发 __setattr__
# def __setattr__(self, key, value):
# print('__setattr__执行')
# # self.key = value #这会造成无限递归
# self.__dict__[key] = value #应该使用它
# f1 = Foo(10)
# print(f1.__dict__)
# f1.z = 2
# print(f1.__dict__)
# del f1.y # 会调用 __delattr__ (类内置函数)
# del f1.x
f1 = Foo(10)
print(f1.y)
print(f1.name) # item 是 name
getattribute(实例 . 调用都先调用此方法,之后根据情况在该方法下调用其他方法)
class Foo:
def __init__(self,x):
self.x = x
def __getattr__(self, item):
print('执行的是getattr')
#实例 .调用都先调用 __getattribute__ ,当遇见 raise AttributeError 时调用 __getattr__
def __getattribute__(self, item):
print('执行的是getattribute')
raise AttributeError('抛出异常') #调用__getattr__ 方法
f1 = Foo(10)
f1.xxxxx
getitem、setitme、delitem
f1 = Foo()
print(f1.age) #调用的是 __getattr__
print(f1['age']) #调用的是 __getitem__
f1.name = 'aa' #调用的是 __setattr__
f1['name'] = 'aa' #调用的是 __setitem__
del f1.name #调用的是 __delattr__
del f1['name'] #调用的是 __delitem__
总结: 用 . 调用是 __getattr__ ; 用 [] 调用是 __getitem__
包装
#通过继承和派生完成包装
class List(list):
def append(self, p):
if type(p) is str:
super().append(p)
def show_middle(self):
mid_index = int(len(self)/2)
return self[mid_index]
# l1 = list("hello world")
# print(l1,type(l1))
l2 = List("hello world1")
print(l2,type(l2))
print(l2.show_middle())
l2.append(11)
l2.append('hh')
print(l2)
授权
授权是包装的一个特性,包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能,其他的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能授权给对象的默认属性
import time
class FileHandle:
def __init__(self,filename,mode='r',encoding='utf-8'):
self.file = open(filename,mode,encoding=encoding)
# def write(self,line):
# t = time.strftime('%Y-%m-%d %X')
# self.file.write('%s %s'%(t,line))
def __getattr__(self, item):
#print(item,type(item))
return getattr(self.file,item)
f1 = FileHandle('a.txt','w')
f1.write('1112\n')
f1.write('2222\n')
#f1.seek(0)
#print(f1.read())