目录
一、类的常用函数
1、issubclass()
检测一个类是否是另外一个类的子类
格式1:issubclass(被检测类,父类)
返回值:布尔值
格式1:issubclass(被检测类,(父类1,父类2,父类3...))
返回值:布尔值
注意:只要有一个类是当前被检测类的父类,那么最终结果就是True
练习1:检查C类是否是A、B类的子类
class A(object):
def __call__(self, *args, **kwargs):
print('call....')
class B(A):
pass
class C(B, A):
pass
b = B()
print(issubclass(C, (A, B))) # True # C是A,B的子类 第二个参数如果是元组,其中有一个是父类就返回True
print(issubclass(C, B)) # True # C是B的子类
2、isinstance()
检测一个对象是否是某个类的对象
格式1:isinstance(对象,类)
返回值:布尔值
格式2:isinstance(对象,(类1,类2,类3...))
返回值:布尔值
注意:只要一个类是当前对象的类,那么最终结果就是True
练习1:检查obj是不是Foo类的对象
class A(object):
def __call__(self, *args, **kwargs):
print('call....')
class B(A):
pass
class C(B, A):
pass
b = B()
print(isinstance(b, B)) # True b是否是B的实例对象
print(isinstance(b, A)) # True b是否是A的实例对象 由于B继承了A
3、反射方法
python面向对象中的反射:通过字符串的形式操作对象相关的属性
python中的一切事物都是对象(都可以使用反射)
四个反射相关的函数
-hasattr :判断是否有此变量,返回bool 值
-getattr : 获取属性值或者获取方法变量的地址
-setattr :给类或者对象设置属性或者方法 (用的场合很少,了解即可)
-delattr: 删除类或者对象的属性或方法(用的场合很少,了解即可)
- 反射类的属性和方法
- 反射对象的属性和方法
- 反射模块的属性和方法
getattr()
获取对象/类中的成员值
格式:getattr(对象,'属性名'[,成员不存在时的默认值])
返回值:成员的值
练习1:获取静态方法和类方法。
class School(object):
lst = ['语文', 99, '数学', 100]
dic = {'a': 'show_student', 'b': 'show_teacher'}
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def func(cls):
print('类方法...')
@staticmethod
def fun1():
print('静态方法')
def show_student(self):
print('展示学生信息')
def show_teacher(self, num):
print(num, '展示学生信息')
# getattr(对象,属性名) 获取属性值或者获取方法变量的地址
# 获取类方法
func = getattr(School, 'func')
func() # 类方法...
# 获取静态方法
fun1 = getattr(School,'fun1')
fun1() # 静态方法
练习2:获取对象的属性值和普通方法。
# 普通方法
show = getattr(School,'show_student')
show(School)
student = School('ZSA',33)
# 普通属性
name = getattr(student,'name')
print(name)
# # 带参方法
show2 = getattr(student,'show_teacher')
show2('a')
'''
展示学生信息
ZSA
a 展示学生信息
'''
hasattr()
检测对象/类是否具有某个成员
格式:hasattr(对象/类,'成员名')
返回值:布尔值
练习1:判断类中是否有dict1静态属性。
# hasattr() 判断是否有方法和属性
student = School('ZSA',33)
print(hasattr(student,'name')) # True
练习2:根据用户输入的key来调用对应的方法。
key = input('>>>')
dic = getattr(School, 'dic')
teacher = School('zx', 34)
value = dic.get(key, '')
ret = hasattr(teacher, value)
if ret:
f = getattr(teacher, dic[key])
f()
else:
pass
'''
>>>a
展示学生信息
'''
setattr()
设置或者添加对象/类中的成员
格式:setattr(对象,'成员名',值)
返回值:None
练习1:给A类添加静态age属性
class A(object):
pass
# 给A类添加静态age属性
setattr(A, 'age', 29)
print(A.age) # 29
练习2:给A类的对象添加name属性
class A(object):
pass
# 给A类的对象添加一个name属性
a = A()
setattr(a,'name','zs')
print(a.name) # zs
delattr()
删除对象/类中的成员
格式: delattr(对象,成员)
返回值:None
练习1:删除a对象的name属性。
class A(object):
pass
# 给A类的对象添加一个name属性
a = A()
setattr(a,'name','zs')
print(a.name) # zs
delattr(a,'name')
print(a.name) # 'A' object has no attribute 'name'
1.反射导入模块中的属性、函数、类
第一个参数是模块名称,第二个参数是变量名称
练习1:反射 test.py模块中的属性、函数和类
test.py
day = '星期一'
def test1():
print('test1...')
class P(object):
def test2(self):
print('test2...')
def test3(name):
print(name)
import test
print(test.day) # 星期一
print(getattr(test,'day')) # 星期一
test1 = getattr(test,'test1')
test1() # test1...
P = getattr(test,'P')
p = P()
p.test2() # test2...
练习2:反射带参数的函数
test3 = getattr(test,'test3')
test3('赵四') # 赵四
2.反射自己模块中的属性和函数
借助sys模块获取当前模块的名称。
练习1:查看当前的所有模块
import sys
print(sys.modules) # 记录当前内存中已经被加载的模块
print(sys.modules['__main__']) # <module '__main__' from 'D:/pycharm工作空间/day17/反射2.py'>
练习2:反射当前模块中的name变量。
# # 反射自己的
import sys
ret = getattr(sys.modules['__main__'],'name')
print(ret) # zs
练习3:反射当前模块中的函数
import sys
def func():
print('sss')
func = getattr(sys.modules['__main__'], 'func')
func() # sss
注意事项:如果本模块作为导入模块 模块的名称就不是 __main__了,因此使用 __name__属性动态获取
fun = getattr(sys.modules[__name__], 'func')
fun()
3.反射内置模块
用法和反射导入模块相同
练习1:反射time模块中的time()函数
import time
s = getattr(time,'time')
print(s()) # 1547648701.3263068
三、迭代器
1.什么是迭代器
拥有__iter__方法和__next__方法的对象就是迭代器
1、迭代
迭代是访问集合元素的一种方式,可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代
2、可迭代协议
协议就是互相规定好的。可迭代协议的定义非常简单,就是内部实现了__iter__方法。
3、迭代器协议:必须拥有__iter__方法和__next__方法。
思考:
- 列举 能被for 循环的内容
list、dic、str、set、tuple、f.open()、range()、enumerate
- dir()方法获取对应数据类型的所有方法。
dir() 获取对应数据类型的所有方法,带有下划线的方法叫双下方法。
例如:print(dir([]))
- 查看 [],{},'',range() 共有的方法:使用集合的交集进行获取。
找到了__iter__ 方法。有此方法的对象就是一个可以被迭代的对象。
查看公有方法:
ret = set(dir([]))&set(dir(()))&set(dir({}))&set(dir(''))&set(dir(range(2)))
print(ret)
'''
{'__iter__', '__len__', '__gt__', '__subclasshook__', '__dir__', '__reduce_ex__', '__str__', '__le__', '__class__', '__setattr__', '__doc__', '__hash__', '__contains__', '__sizeof__', '__reduce__', '__init_subclass__', '__eq__', '__delattr__', '__new__', '__ge__', '__getattribute__', '__lt__', '__ne__', '__repr__', '__format__', '__init__', '__getitem__'}
'''
循环整数:
for i in 123:
print(i) # TypeError: 'int' object is not iterable
判断int类型是否有__iter__方法
print('__iter__' in dir(int)) # False
print('__iter__' in dir(bool)) # False
只要含有__iter__,就是可迭代的
四、__iter__方法的作用是返回一个迭代器。
一个列表执行了__iter__方法后返回的值就是一个迭代器
print([].__iter__()) # <list_iterator object at 0x0000000001E7C5F8>
五、打印一下迭代器中的方法。
print(dir([].__iter__())) # 查看这个迭代器的所有方法
'''
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
'''
g = ['a', 'b', 'c'].__iter__()
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
'''
a
b
c
'''
原来__iter__()中有一个__next__()方法,这个方法可以迭代
for循环原理
1.for循环一个可迭代的对象(实现__iter__方法)
2.__iter__方法返回一个迭代器(迭代器实现了__iter__方法和__next__方法)
3.for先判断对象地方可迭代,然后调用迭代器的__next__方法获取值。
迭代器作用
节约内存,取得时候在生成数据,python2.7的时候range()方法就立刻生成了数据
占用了大量的内存空间。
应用场景
1、数据类型转换 例如 list和元组之间的转换底层就是使用的迭代器