类型检测

isinstance(obj,cls)

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

  1. class Foo(object):
  2. pass
  3. obj = Foo()
  4. print(isinstance(obj, Foo)) # True
  5. a = 'hello'
  6. print(isinstance(a, str)) # True
  7. b= ['hello']
  8. print(isinstance(b, list)) # True
  9. c= ('hello') # str类型
  10. c= ('hello', ) # 注意,元素只有一个元素,必须加逗号,否则是这个元素的类型
  11. print(isinstance(c, tuple)) # True

issubclass(sub,super)

检查sub类是否是 super 类的派生类

  1. class A:
  2. pass
  3. class B(A):
  4. pass
  5. class C(B):
  6. pass
  7. print(issubclass(B, A)) # true
  8. print(issubclass(C, A)) # true

item系列

  1. # item系列
  2. class Foo(object): # Dict
  3. def __init__(self, name):
  4. self.name = name
  5. def __getitem__(self, item): # item='namexxx'
  6. # print('getitem...')
  7. return self.__dict__.get(item)
  8. def __setitem__(self, key, value):
  9. # print('setitem...')
  10. # print(key,value)
  11. self.__dict__[key] = value
  12. def __delitem__(self, key):
  13. # print('delitem...')
  14. # print(key)
  15. del self.__dict__[key]
  16. obj = Foo('ecithy')
  17. print(obj.__dict__)
  18. # 查看属性:
  19. # obj.属性名
  20. print(obj['namexxx']) #obj.name
  21. # 设置属性:
  22. obj.sex='male'
  23. obj['sex']='male'
  24. print(obj.__dict__)
  25. print(obj.sex)
  26. # 删除属性
  27. del obj.name
  28. # del obj['name']
  29. print(obj.__dict__)

字符串系列

改变对象的字符串显示__str____repr__

  1. class School:
  2. def __init__(self, name, addr, type):
  3. self.name = name
  4. self.addr = addr
  5. self.type = type
  6. def __repr__(self):
  7. return 'School(%s,%s)' % (self.name, self.addr)
  8. def __str__(self):
  9. return '(%s,%s)' % (self.name, self.addr)
  10. s1 = School('mufeng', '北京', '私立')
  11. print('from repr: ', repr(s1))
  12. print('from str: ', str(s1))
  13. print(repr(s1))
  14. print(s1)
  15. '''
  16. str函数或者print函数--->obj.__str__()
  17. repr或者交互式解释器--->obj.__repr__()
  18. 如果__str__没有被定义,那么就会使用__repr__来代替输出
  19. 注意:这俩方法的返回值必须是字符串,否则抛出异常
  20. '''

对象调用

__call__
对象后面加括号,触发执行。

  1. class Foo:
  2. def __init__(self):
  3. pass
  4. def __call__(self, *args, **kwargs):
  5. print('__call__')
  6. obj = Foo() # 执行 __init__
  7. obj() # 执行 __call__

垃圾回收

__del__

析构方法,当对象在内存中被释放时,自动触发执行。

注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义del,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了del

  1. class Foo:
  2. def __del__(self):
  3. '对象执行结束后一会执行'
  4. print('执行我啦')
  5. f1 = Foo()
  6. del f1 # 立刻执行
  7. print('------->')

典型的应用场景:

创建数据库类,用该类实例化出数据库链接对象,对象本身是存放于用户空间内存中,而链接则是由操作系统管理的,存放于内核空间内存中 当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制del,在对象被删除前向操作系统发起关闭数据库链接的系统调用,回收资源

这与文件处理是一个道理

  1. f=open('a.txt') #做了两件事,在用户空间拿到一个f变量,在操作系统内核空间打开一个文件
  2. del f #只回收用户空间的f,操作系统的文件还处于打开状态
  3. #所以我们应该在del f之前保证f.close()执行,即便是没有del,程序执行完毕也会自动del清理资源,于是文件操作的正确用法应该是
  4. f=open('a.txt')
  5. 读写...
  6. f.close()
  7. 很多情况下大家都容易忽略f.close,这就用到了with上下文管理

上下文管理

__enter____exit__

即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明enterexit方法

作用:

  1. 使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
  2. 在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在exit中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处 ```python class Open: def init(self, name):

    1. self.name = name

    def enter(self):

    1. print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
    2. return self

    def exit(self, exc_type, exc_val, exc_tb):

    1. print('with中代码块执行完毕时执行我啊')

with Open(‘a.txt’) as f: print(‘=====>执行代码块’) print(f, f.name)

  1. __exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行
  2. 如果__exit()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行
  3. ```python
  4. class Open:
  5. def __init__(self,name):
  6. self.name=name
  7. def __enter__(self):
  8. print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
  9. def __exit__(self, exc_type, exc_val, exc_tb):
  10. print('with中代码块执行完毕时执行我啊')
  11. print(exc_type)
  12. print(exc_val)
  13. print(exc_tb)
  14. return True
  15. with Open('a.txt') as f:
  16. print('=====>执行代码块')
  17. raise AttributeError('***着火啦,救火啊***')
  18. print('0'*10) #------------------------------->会执行

迭代器协议

把类变成迭代器
迭代器类型的定义:

  • 1.当类中定义了 iternext 两个方法。
  • 2.iter 方法需要返回对象本身,即:self
  • 3. next 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。

官方文档:https://docs.python.org/3/library/stdtypes.html#iterator-types

  1. # 创建 迭代器类型 :
  2. class IT(object):
  3. def __init__(self):
  4. self.counter = 0
  5. def __iter__(self):
  6. return self
  7. def __next__(self):
  8. self.counter += 1
  9. if self.counter == 3:
  10. raise StopIteration()
  11. return self.counter
  12. # 根据类实例化创建一个迭代器对象:
  13. obj1 = IT()
  14. # v1 = obj1.__next__()
  15. # v2 = obj1.__next__()
  16. # v3 = obj1.__next__() # 抛出异常
  17. v1 = next(obj1) # obj1.__next__()
  18. print(v1)
  19. v2 = next(obj1)
  20. print(v2)
  21. v3 = next(obj1)
  22. print(v3)
  23. obj2 = IT()
  24. for item in obj2: # 首先会执行迭代器对象的__iter__方法并获取返回值,一直去反复的执行 next(对象)
  25. print(item)
  26. 迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration
  27. for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行的next取值(有异常StopIteration则终止循环)。
  1. from collections import Iterable,Iterator
  2. class Range:
  3. def __init__(self,n,stop,step=1):
  4. self.n=n
  5. self.stop=stop
  6. self.step=step
  7. def __next__(self):
  8. if self.n >= self.stop:
  9. raise StopIteration
  10. x=self.n
  11. self.n+=self.step
  12. return x
  13. def __iter__(self):
  14. return self
  15. print(isinstance(Range(1,7,2), Iterator)) # True
  16. for i in Range(1,7,2):
  17. print(i)
  18. # 输出 1 3 5

生成器

把函数变成迭代器

  1. # 创建生成器函数
  2. def func():
  3. yield 1
  4. yield 2
  5. # 创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:__iter__、__next__ 方法。
  6. obj1 = func()
  7. v1 = next(obj1)
  8. print(v1)
  9. v2 = next(obj1)
  10. print(v2)
  11. v3 = next(obj1)
  12. print(v3)
  13. obj2 = func()
  14. for item in obj2:
  15. print(item)
  16. 如果按照迭代器的规定来看,其实生成器类也是一种特殊的迭代器类(生成器也是一个中特殊的迭代器)。

可迭代对象

如果一个类中有iter方法且返回一个迭代器对象 ;则我们称以这个类创建的对象为可迭代对象。

  1. class Foo(object):
  2. def __iter__(self):
  3. return 迭代器对象(生成器对象)
  4. obj = Foo() # obj是 可迭代对象。
  5. # 可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行 __iter__ 方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
  6. for item in obj:
  7. pass

类的描述信息

__doc__
Python中一切皆对象,函数的基类也是object

  1. def test():
  2. '我是函数描述信息'
  3. pass
  4. class Foo:
  5. '我是类描述信息'
  6. pass
  7. print(Foo.__doc__) # 我是类描述信息
  8. print(test.__doc__) # 我是函数描述信息