1.isinstance和issubclass
1.1 isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo(object):
pass
obj = Foo()
isinstance(obj, Foo)
1.2 issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object):
pass
class Bar(Foo):
pass
issubclass(Bar, Foo)
2.反射
通过字符串的形式操作对象相关的属性,下列方法适用于类和对象(一切皆对象,类本身也是一个对象)。
hasattr 检测是否含有某属性
getattr 获得属性
setattr设置属性
delattr 删除属性
class Foo:
#四个方法的使用演示
f = '类的静态变量'
def __init__(self,name,age):
self.name=name
self.age=age
def say_hi(self):
print('hi,%s'%self.name)
obj=Foo('egon',73)
#检测是否含有某属性
print(hasattr(obj,'name'))
print(hasattr(obj,'say_hi'))
#获取属性
n=getattr(obj,'name')
print(n)
func=getattr(obj,'say_hi')
func()
print(getattr(obj,'aaaaaaaa','不存在啊')) #报错
#设置属性
setattr(obj,'sb',True)
setattr(obj,'show_name',lambda self:self.name+'sb')
print(obj.__dict__)
print(obj.show_name(obj))
#删除属性
delattr(obj,'age')
delattr(obj,'show_name')
delattr(obj,'show_name111')#不存在,则报错
print(obj.__dict__)
class Foo(object):
staticField = "old boy"
def __init__(self):
self.name = 'wupeiqi'
def func(self):
return 'func'
@staticmethod
def bar():
return 'bar'
print getattr(Foo, 'staticField') #获得静态属性
print getattr(Foo, 'func') #获得方法
print getattr(Foo, 'bar') #获得方法
import time
#导入其他模块,利用反射查找该模块是否存在某个方法
print(hasattr(time,'sleep'))
3. __str__和__repr__
打印一个对象的时候,就是调用__str__,repr 是str的备胎,但str不能做repr的备胎
# 双下方法
# obj.__str__ str(obj)
# obj.__repr__ repr(obj)
class Teacher:
def __init__(self,name,salary):
self.name = name
self.salary = salary
def __str__(self):
return "Teacher's object :%s"%self.name
def __repr__(self):
return str(self.__dict__)
def func(self):
return 'wahaha'
nezha = Teacher('哪吒',250)
print(nezha) # 打印一个对象的时候,就是调用a.__str__
print(repr(nezha)) #调用__repr__
print('>>> %s'%nezha) # %s str() 直接打印 实际上都是走的__str__
print('>>> %r'%nezha) #%r 实际上都是走的__repr__
#a.__str__ --> object
# object 里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址
# l = [1,2,3,4,5] # 实例化 实例化了一个列表类的对象
# print(l)
# print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串
# 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
# repr(),只会找__repr__,如果没有找父类的
4. item系列
__getitem__\__setitem__\__delitem__
class Foo:
def __init__(self,name):
self.name=name
def __getitem__(self, item):
print(self.__dict__[item])
def __setitem__(self, key, value):
self.__dict__[key]=value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key时,我执行')
self.__dict__.pop(item)
f1=Foo('sb')
f1['age']=18
f1['age1']=19
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)
5. __del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class Foo:
def __del__(self):
print('执行我啦')
f1=Foo()
del f1
print('------->')
#输出结果
'执行我啦
------->
简单示范'
6. __new__
# __init__ 初始化方法
# __new__ 构造方法 : 创建一个对象,在init前执行
class A:
def __init__(self):
self.x = 1
print('in init function')
def __new__(cls, *args, **kwargs):
print('in new function')
return object.__new__(A)
a1 = A()
a2 = A()
a3 = A()
print(a1.x)
print(a2)
print(a3)
print(a.x)
# 单例模式
# 一个类 始终 只有 一个 实例
# 当你第一次实例化这个类的时候 就创建一个实例化的对象
# 当你之后再来实例化的时候 就用之前创建的对象
class A:
__instance = False
def __init__(self,name,age):
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
if cls.__instance:
return cls.__instance
cls.__instance = object.__new__(cls)
return cls.__instance
egon = A('egg',38)
egon.cloth = '小花袄'
nezha = A('nazha',25)
print(nezha)
print(egon)
print(nezha.name)
print(egon.name)
print(nezha.cloth)
7. __call__
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
8. __len__
class A:
def __init__(self):
self.a = 1
self.b = 2
def __len__(self):
return len(self.__dict__)
a = A()
print(len(a))
9. __eq__
class A:
def __init__(self,name):
self.name = name
def __eq__(self, other):
if self.__dict__ == other.__dict__:
return True
else:
return False
ob1 = A('egon')
ob2 = A('egg')
print(ob1 == ob2) #不使用__eq__,等号左右是对象的地址,使用__eq__等号左右是__eq__函数的返回值
10. __hash__
用于获取取一个对象(字符串或者数值等)的哈希值。
class A:
def __init__(self):
self.a = 1
self.b = 2
def __hash__(self):
return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))
可哈希的集合(hashed collections),需要集合的元素实现了__eq__
和__hash__
,而这两个方法可以作一个形象的比喻:
哈希集合就是很多个桶,但每个桶里面只能放一个球。__hash__
函数的作用就是找到桶的位置,到底是几号桶。__eq__
函数的作用就是当桶里面已经有一个球了,但又来了一个球,它声称它也应该装进这个桶里面(__hash__
函数给它说了桶的位置),双方僵持不下,那就得用__eq__
函数来判断这两个球是不是相等的(equal),如果是判断是相等的,那么后来那个球就不应该放进桶里,哈希集合维持现状。
class Foo:
def __init__(self, item):
self.item = item
def __eq__(self, other):
print('使用了equal函数的对象的id',id(self))
if isinstance(other, self.__class__):
return self.__dict__ == other.__dict__
else:
return False
def __hash__(self):
print('f'+str(self.item)+'使用了hash函数')
return hash(self.item)
f1 = Foo(1)
f2 = Foo(2)
f3 = Foo(3)
fset = set([f1, f2, f3])
print(fset)
print()
f = Foo(3)
fset.add(f)
print('f3的id:',id(f3))
print('f的id:',id(f))
#输出结果
'f1使用了hash函数
f2使用了hash函数
f3使用了hash函数
{<__main__.Foo object at 0x0000023769AB67C0>, <__main__.Foo object at
0x0000023769AC5C10>, <__main__.Foo object at 0x0000023769AC5C40>}
f3使用了hash函数
使用了equal函数的对象的id 2437019360320
f3的id: 2437019360320
f的id: 2437019360368'
11. with和__enter__,__exit__
python中的with语句使用于对资源进行访问的场合,保证不管处理过程中是否发生错误或者异常都会执行规定的__exit__(“清理”)操作,释放被访问的资源,比如有文件读写后自动关闭、线程中锁的自动获取和释放等。
with EXPR as VAR:
BLOCK
#执行EXPR,生成上下文管理器context_manager;
#获取上下文管理器的__exit()__方法,并保存起来用于之后的调用;
#调用上下文管理器的__enter__()方法;如果使用了as子句,则将__enter__()方法的返回值赋值给as子句中#的VAR;
#执行BLOCK中的表达式;
#不管是否执行过程中是否发生了异常,执行上下文管理器的__exit__()方法,__exit__()方法负责执行“清
#理”工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句#break/continue/return,则以None作为参数调用__exit__(None, None, None);如果执行过程中出现异
#常,则使用sys.exc_info得到的异常信息为参数调用__exit__(exc_type, exc_value, exc_traceback);
#出现异常时,如果__exit__(type, value, traceback)返回False,则会重新抛出异常,让with之外的语句
#逻辑来处理异常,这也是通用做法;如果返回True,则忽略异常,不再对异常进行处理。
class A:
def __enter__(self):
print('before')
def __exit__(self, exc_type, exc_val, exc_tb):
print('after')
#with语句
with A() as a:
print('123')
#with语句和init
class A:
def __init__(self):
print('init')
def __enter__(self):
print('before')
def __exit__(self, exc_type, exc_val, exc_tb):
print('after')
with A() as a:
print('123')
#with和文件操作
class Myfile:
def __init__(self,path,mode='r',encoding = 'utf-8'):
self.path = path
self.mode = mode
self.encoding = encoding
def __enter__(self):
self.f = open(self.path, mode=self.mode, encoding=self.encoding)
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
self.f.close()
with Myfile('file',mode='w') as f:
f.write('wahaha')
12. __len__
class A:
def __init__(self):
self.a = 1
self.b = 2
def __len__(self):
return len(self.__dict__)
a = A()
print(len(a))