python类的常用函数、反射、迭代器

目录

一、类的常用函数

1、issubclass()

2、isinstance()

3、反射方法

hasattr()

setattr()

delattr()

1.反射导入模块中的属性、函数、类

2.反射自己模块中的属性和函数

3.反射内置模块

三、迭代器

1.什么是迭代器


一、类的常用函数

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和元组之间的转换底层就是使用的迭代器

猜你喜欢

转载自blog.csdn.net/weixin_42223833/article/details/86515588