21day学通python_python学习Day21--内置函数、反射

【知识点】

1、isinstance()  判断对象所属类型,包含继承关系

type()与isinstance()的区别

1 classmystr(str):pass2 ms=mystr('alex')3 print(ms)4 print(type(ms) isstr) # 不包含继承关系,只管一层5 print(isinstance(ms,str)) # 包含所有的继承关系

2、issubclass(B,A)    判断B是不是A的子类(判断类与类之间的继承关系)

3、反射:用字符串数据类型的变量名来访问这个变量的值

方法:getattr   hasattr    setattr     delattr

(1)在类的应用:静态属性(静态字段)、类方法、静态方法

命名空间.XXX=getattr(命名空间,'XXX')   属性直接用,方法在后加()

1 classStudent:2 ROLE='STUDENT'

3

4 @classmethod5 def check_course(cls):6 print("查看课程了")7

8 @staticmethod9 def login():10 print("登录")11 # 反射查看属性12 print(Student.ROLE) # 通过类名调用13 print(getattr(Student,'ROLE'))14

15 # 反射调用方法16 getattr(Student,'check_course')() # 查看课程了 # 类方法17 getattr(Student,'login')() # 登录 # 静态方法18

19 num=input("请输入要调用的方法>>>")20 ifhasattr(Student,num): # 如果输入的num是Student这个命名空间里的方法,则返回True,否则返回Flase21 getattr(Student,num)()22 else:23 num = input("你输入的有误,请重新输入要调用的方法>>>")

(2)在对象中应用:

1 # 在对象中2 classA():3 def __init__(self,name):4 self.name=name5

6 def func(self):7 print("in func")8

9 a=A('123')10 print(a.name) # 123

11 print(getattr(a,'name')) # 123

12 getattr(a,'func')() # in func

(3)在模块中

1 # 在模块2 import os3 '''4 # os.rename('__init__.py','init')5 # getattr(os,'rename')('init','__init__.py')6 rename=os.rename7 rename2=getattr(os,'rename')8 rename('__init__.py','init') # os.rename('__init__.py','init')9 rename2('init','__init__.py') # getattr(os,'rename')('init','__init__.py')10 '''11 # 反射自己模块中的内容,找到自己当前文件所在的命名空间12 def wahaha():13 print("wahaha")14

15 def qqxing():16 print("qqxing")17

18 # wahaha()19 # qqxing()20

21 import sys22 # print(sys.modules)23 # sys.modules 这个方法,表示所有在当前这个python程序中导入的模块24 # print(sys.modules['__main__'])25 my_file=sys.modules['__main__'] # 当前文件所在模块26 # my_file.wahaha()27

28 getattr(my_file,'wahaha')() # wahaha

【反射总结】

hasattr    getattr

① 类名.名字

getattr(类名,'名字')

② 对象名.名字

getattr(对象,'名字')

③ 模块名.名字

import 模块

getattr(模块,'名字')

④ 自己文件.名字

import sys

getattr(sys.modules['__main__'],'名字')

【反射的应用】

1 # 一个选课查询系统2 classManager():3 OPERATE_DIC=[4 ('create_student','创建学生账号'),5 ('create_course','创建学生课程'),6 ('check_student','查看学生信息')7 ]8

9 def __init__(self,name):10 self.name=name11

12 def create_student(self):13 print("创建学生账号")14

15 def create_course(self):16 print("创建学生课程")17

18 def check_student(self):19 print("查看学生信息")20

21

22 classStudent():23 OPERATE_DIC =[24 ('choose_course', '学生选择课程'),25 ('check_course', '学生查询课程')26 ]27

28 def __init__(self,name):29 self.name=name30

31 def choose_course(self):32 print("学生选择课程")33

34 def check_course(self):35 print("学生查询课程")36

37

38 def login():39 count=1

40 while count<4:41 username=input("请输入用户名:")42 password=input("请输入密码:")43 with open('userinfo',mode='r',encoding='utf-8') asf:44 for line inf:45 user,pwd,ident=line.strip().split('|')46 if username == user and password ==pwd:47 print("登录成功")48 returnusername,ident49 else:50 print("输入错误,请重新输入,你还有%d次机会" % (3-count))51 break

52 count+=1

53

54 import sys55 def main():56 whileTrue:57 user,id=login()58 file=sys.modules['__main__'] # 拿到自己当前所在的模块59 cls=getattr(file,id) # id=manager,student 所以可以拿到相应的类60 obj=cls(user) # 类的实例化,并传入参数61 lst=getattr(cls,'OPERATE_DIC') # 通过类拿到静态属性值62 for num,el in enumerate(lst,1): # enumerate()是将列表中元素添加上序号,从1开始则需要添加起始参数163 print(num,el[1]) # num是序号,el是元组 el[1]获取元组的第二个参数64 i=int(input('请输入要选择项序号:'))65 getattr(obj,lst[i-1][0]) () # lst[i-1][0]得到的是字符串,故用getattr()方法66 main()

4、内置函数

__名字__

# 类中的特殊方法\内置方法

#双下方法

#魔术方法

类中的每一个双下方法都有它自己的特殊意义

(1)__call__ 方法

对象() 相当于调用__call__方法

类名()() 相当于先实例化一个对象,再对对象()。与上面结果一样

1 # __call__2 classA:3 def __call__(self,*args,**kwargs):4 print("执行call方法了")5

6 classB:7 def __init__(self,cls):8 print("在实例化A之前做一些事")9 self.a=cls()10 self.a()11 print("在实例化A之后做一些事")12 # a=A()13 # a() # 相当于调用__call__方法14 #A()() # 和上面结果一样,相当于调用__call__15 B(A)

(2)__len__方法

len(obj) 相当于调用了这个obj的__len__方法

__len__方法return的值就是len函数返回的值

#如果一个obj对象没有__len__方法,那么len函数就会报错

1 # __len__方法2 #内置函数与类的内置方法是有奸情的3 classMylist:4 def __init__(self):5 self.lst=[1,2,3,4,5,6]6 self.name='123'

7 self.age=45

8

9 def __len__(self):10 print("执行__len__方法了")11 returnlen(self.__dict__)12 m=Mylist()13 print(len(m)) # 执行__len__方法了 3

(3)__new__方法(构造方法)

在执行__init__之前,开辟一个空间。

1 # __new__构造方法2 classSingle:3 def __new__(cls,*args,**kwargs):4 obj=object.__new__(cls)5 print("在new方法里",obj)6 returnobj7

8 def __init__(self):9 print("在init方法里",self)10 #1、开辟一个空间,属于对象的11 #2、把这个对象的空间传给self,执行init12 #3、将这个对象的空间返回给调用者13 obj=Single() #结果:在new方法里 <__main__.single object at>

14 #结果:在init方法里 <__main__.single object at>

15 #若是类中没有__nem__方法,则会调用object里的__new__来开辟空间

【一道面试题】

写出一个单例类?

#1、单例:如果一个类,从头到尾只能有一个实例(说明从头到尾只开辟了一块属于对象的空间),那么这个类就是一个单例类。

单例的例子代码:

1 # 写一个单例类2 classSingle:3 __ISINSTANCE=None4 def __new__(cls,*args,**kwargs):5 ifnot cls.__ISINSTANCE:6 cls.__ISINSTANCE=object.__new__(cls)7 returncls.__ISINSTANCE8

9 def __init__(self,name,age):10 self.name=name11 self.age=age12

13 s1=Single('太白',23)14 s2=Single('Alex',26)15 print(s1.name) # Alex16 print(s2.name) # Alex17 # 原因:首先开辟一个空间,并且只有一个空间。最开始将name赋值“太白”,age赋值23,18 # 然后执行S2=Single('Alex',26),由于只有一个空间,故将此前的值覆盖掉,所以最后打印都是“Alex”

注意:上述例子首先开辟了一个空间,并且只有一个空间。最开始将name赋值“太白”,age赋值23,然后执行S2=Single('Alex',26),由于只有一个空间,故将此前的值覆盖掉,所以最后打印都是“Alex”。

(4)__str__方法

print(对象)  相当于调用一个对象的__str__方法

str(obj)   相当于执行了obj.__str__方法

'%s' % obj  相当于执行obj.__str__方法

1 # __str__方法2 classStudent:3 def __str__(self):4 return '%s %s %s' %(self.school,self.stu_cls,self.name)5

6 def __init__(self,name,stu_cls):7 self.school='oldboy'

8 self.name=name9 self.stu_cls=stu_cls10

11 he=Student('菏泽微','py14')12 # print(he) # 执行了__str__方法 结果:oldboy py14 菏泽微13 # print(str(he)) # 也执行了__str__方法,结果同上14 print('学生1:%s' % he) # 也执行了__str__方法,结果同上

【小结】所有的双下方法,没有需要你在外面调用的,而是总有一些其他的 内置函数 特殊的语法 来自动触发这些双下方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值