类型检测
isinstance(obj,cls)
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo(object):
pass
obj = Foo()
print(isinstance(obj, Foo)) # True
a = 'hello'
print(isinstance(a, str)) # True
b= ['hello']
print(isinstance(b, list)) # True
c= ('hello') # str类型
c= ('hello', ) # 注意,元素只有一个元素,必须加逗号,否则是这个元素的类型
print(isinstance(c, tuple)) # True
issubclass(sub,super)
检查sub类是否是 super 类的派生类
class A:
pass
class B(A):
pass
class C(B):
pass
print(issubclass(B, A)) # true
print(issubclass(C, A)) # true
item系列
# item系列
class Foo(object): # Dict
def __init__(self, name):
self.name = name
def __getitem__(self, item): # item='namexxx'
# print('getitem...')
return self.__dict__.get(item)
def __setitem__(self, key, value):
# print('setitem...')
# print(key,value)
self.__dict__[key] = value
def __delitem__(self, key):
# print('delitem...')
# print(key)
del self.__dict__[key]
obj = Foo('ecithy')
print(obj.__dict__)
# 查看属性:
# obj.属性名
print(obj['namexxx']) #obj.name
# 设置属性:
obj.sex='male'
obj['sex']='male'
print(obj.__dict__)
print(obj.sex)
# 删除属性
del obj.name
# del obj['name']
print(obj.__dict__)
字符串系列
改变对象的字符串显示__str__
、__repr__
class School:
def __init__(self, name, addr, type):
self.name = name
self.addr = addr
self.type = type
def __repr__(self):
return 'School(%s,%s)' % (self.name, self.addr)
def __str__(self):
return '(%s,%s)' % (self.name, self.addr)
s1 = School('mufeng', '北京', '私立')
print('from repr: ', repr(s1))
print('from str: ', str(s1))
print(repr(s1))
print(s1)
'''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
对象调用
__call__
对象后面加括号,触发执行。
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
垃圾回收
__del__
析构方法,当对象在内存中被释放时,自动触发执行。
注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义del,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了del。
class Foo:
def __del__(self):
'对象执行结束后一会执行'
print('执行我啦')
f1 = Foo()
del f1 # 立刻执行
print('------->')
典型的应用场景:
创建数据库类,用该类实例化出数据库链接对象,对象本身是存放于用户空间内存中,而链接则是由操作系统管理的,存放于内核空间内存中 当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制del,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源
这与文件处理是一个道理
f=open('a.txt') #做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件
del f #只回收用户空间的f,操作系统的文件还处于打开状态
#所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是
f=open('a.txt')
读写...
f.close()
很多情况下大家都容易忽略f.close,这就用到了with上下文管理
上下文管理
__enter__
、__exit__
即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明enter和exit方法
作用:
- 使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在exit中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处 ```python class Open: def init(self, name):
self.name = name
def enter(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
return self
def exit(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
with Open(‘a.txt’) as f: print(‘=====>执行代码块’) print(f, f.name)
__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
```python
class Open:
def __init__(self,name):
self.name=name
def __enter__(self):
print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
def __exit__(self, exc_type, exc_val, exc_tb):
print('with中代码块执行完毕时执行我啊')
print(exc_type)
print(exc_val)
print(exc_tb)
return True
with Open('a.txt') as f:
print('=====>执行代码块')
raise AttributeError('***着火啦,救火啊***')
print('0'*10) #------------------------------->会执行
迭代器协议
把类变成迭代器
迭代器类型的定义:
- 1.当类中定义了 iter 和 next 两个方法。
- 2.iter 方法需要返回对象本身,即:self
- 3. next 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。
官方文档:https://docs.python.org/3/library/stdtypes.html#iterator-types
# 创建 迭代器类型 :
class IT(object):
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration()
return self.counter
# 根据类实例化创建一个迭代器对象:
obj1 = IT()
# v1 = obj1.__next__()
# v2 = obj1.__next__()
# v3 = obj1.__next__() # 抛出异常
v1 = next(obj1) # obj1.__next__()
print(v1)
v2 = next(obj1)
print(v2)
v3 = next(obj1)
print(v3)
obj2 = IT()
for item in obj2: # 首先会执行迭代器对象的__iter__方法并获取返回值,一直去反复的执行 next(对象)
print(item)
迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration。
for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行的next取值(有异常StopIteration则终止循环)。
from collections import Iterable,Iterator
class Range:
def __init__(self,n,stop,step=1):
self.n=n
self.stop=stop
self.step=step
def __next__(self):
if self.n >= self.stop:
raise StopIteration
x=self.n
self.n+=self.step
return x
def __iter__(self):
return self
print(isinstance(Range(1,7,2), Iterator)) # True
for i in Range(1,7,2):
print(i)
# 输出 1 3 5
生成器
把函数变成迭代器
# 创建生成器函数
def func():
yield 1
yield 2
# 创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__、__next__ 方法。
obj1 = func()
v1 = next(obj1)
print(v1)
v2 = next(obj1)
print(v2)
v3 = next(obj1)
print(v3)
obj2 = func()
for item in obj2:
print(item)
如果按照迭代器的规定来看,其实生成器类也是一种特殊的迭代器类(生成器也是一个中特殊的迭代器)。
可迭代对象
如果一个类中有iter方法且返回一个迭代器对象 ;则我们称以这个类创建的对象为可迭代对象。
class Foo(object):
def __iter__(self):
return 迭代器对象(生成器对象)
obj = Foo() # obj是 可迭代对象。
# 可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行 __iter__ 方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
for item in obj:
pass
类的描述信息
__doc__
Python中一切皆对象,函数的基类也是object
def test():
'我是函数描述信息'
pass
class Foo:
'我是类描述信息'
pass
print(Foo.__doc__) # 我是类描述信息
print(test.__doc__) # 我是函数描述信息