翼度科技»论坛 编程开发 python 查看内容

组合,反射,魔术方法

6

主题

6

帖子

18

积分

新手上路

Rank: 1

积分
18
组合,反射,魔术方法


  • 组合
  • 反射
  • 魔术方法
组合
  1. 什么是组合?
  2.         组合就是,一个对象拥有一个属性,该属性的值是另外一个对象.
  3. """什么场景下使用继承? 什么场景下使用组合?"""
  4. 继承一般情况用在:什么是什么的情况 is
  5. 组合一般用在:什么有什么的情况 has
复制代码
  1. class Foo:
  2.     def __init__(self, m):
  3.         self.m = m
  4. class Bar():
  5.     def __init__(self, n):
  6.         self.n = n
  7. """一个对象拥有一个属性,该属性的值是另外一个对象."""
  8. obj=Bar(10)
  9. obj1 = Foo(20)
  10. # 超级对象,通过一个属性可以访问到另外一个对象的值
  11. obj.x=obj1
  12. print(obj.x.m)  
复制代码
案例
  1. 组合案例:选课
  2. class People():#父类
  3.     school = 'SH'
  4.     def __init__(self, name, age, gender, course_name=None, course_price=None, course_period=None):
  5.         self.name = name
  6.         self.age = age
  7.         self.gender = gender
  8.         # self.course_name = course_name
  9.         # self.course_price = course_price
  10.         # self.course_period = course_period
  11. class Admin(People):#管理员
  12.     def __init__(self, name, age, gender):
  13.         super().__init__(name, age, gender)
  14. class Course():#科目
  15.     def __init__(self, name, price, period):
  16.         self.name = name
  17.         self.price = price
  18.         self.period = period
  19. python=Course('python', 10000, '6mon')#添加科目
  20. linux=Course('linux', 20000, '5mon')
  21. # print(python.name)
  22. # print(python.price)
  23. # print(python.period)
  24. class Student(People):
  25.     #学生
  26.     def __init__(self, name, age, gender, course=None):
  27.         super().__init__(name, age, gender)
  28.         if course is None:
  29.             course = []
  30.         self.course = course
  31. stu = Student('kevin', 20, 'male')
  32. stu.course.append(python.name)#进行组合
  33. stu.course.append(linux.name)#组合
  34. print(stu.course) # [<__main__.Course object at 0x000001F258F86B80>, <__main__.Course object at 0x000001F258F511C0>]
  35. # stu.course: []
  36. for i in stu.course:
  37.     print(i)
  38. class Teacher(People):#老师
  39.     def __init__(self, name, age, gender, level):
  40.         super().__init__(name, age, gender)
  41.         self.level = level
  42. tea = Teacher('ly', 19, 'female', 10)
  43. # print(tea.course_name)
  44. tea.course=linux#创建一个course,将linux组合
  45. print(tea.course.period)
  46. print(tea.course.name)
  47. print(tea.course.price)
复制代码
反射
  1. 在Python中,反射指的是通过字符串来操作对象的属性,涉及到四个内置函数的使用(Python中一切皆对象,类和对象都可以用下述四个方法)
  2. 四个内置函数:
  3.     getattr: 获取属性 ##### 用的最多
  4.     setattr:设置属性
  5.     hasattr:判断是否有某个属性
  6.     delattr:删除
复制代码
getattr   获取属性
  1. class Student():
  2.     school = 'SH'
  3.     def __init__(self,name, age):
  4.         self.name=name
  5.         self.age = age
  6.     def func(self):
  7.         print('from func')
  8.     def index(self):
  9.         print('from index')
  10. stu = Student('kevin', 20)
  11. # attr=input('请输入你要操作的属性名:')
  12. """反射:就是通过字符串的形式来操作对象的属性"""
  13. # 1. 获取属性
  14. """当你查询的属性不存在的时候,如果给了第三个参数,就返回第三个参数"""
  15. print(stu.school)
  16. res = getattr(stu, 'school1', 666)
  17. print(res)
  18. res1=getattr(stu,'shool',666)
  19. print(res1)#666
  20. res2=getattr(stu,'name')
  21. print(res2)
  22. ### 函数的用法
  23. """必须掌握!!!!!!"""
  24. res=getattr(stu, 'func1', stu.index)#等同于stu.func1,不存在该属性则返回默认值stu.index
  25. res()
复制代码
setattr:设置属性
  1. ### 设置
  2. class Student():
  3.     school = 'SH'
  4.     def __init__(self,name, age):
  5.         self.name=name
  6.         self.age = age
  7.     def func(self):
  8.         print('from func')
  9.     def index(self):
  10.         print('from index')
  11. stu = Student('kevin', 20)
  12. setattr(stu, 'x', 666) # stu.x=666
  13. print(stu.__dict__)#{'name': 'kevin', 'age': 20, 'x': 666}
复制代码
hasattr:判断是否有某个属性
  1. #判断
  2. class Student():
  3.     school = 'SH'
  4.     def __init__(self,name, age):
  5.         self.name=name
  6.         self.age = age
  7.     def func(self):
  8.         print('from func')
  9.     def index(self):
  10.         print('from index')
  11. stu = Student('kevin', 20)
  12. print(hasattr(stu, 'func'))#True
  13. print(hasattr(stu,'qwe'))#False
  14. if hasattr(stu, 'func'):
  15.     getattr(stu, 'func')()
  16. else:
  17.     pass
复制代码
delattr:删除
  1. class Student():
  2.     school = 'SH'
  3.     def __init__(self,name, age):
  4.         self.name=name
  5.         self.age = age
  6.     def func(self):
  7.         print('from func')
  8.     def index(self):
  9.         print('from index')
  10. stu = Student('kevin', 20)
  11. delattr(stu, 'name')
  12. print(stu.__dict__)#{'age': 20}
复制代码
魔术方法

init             str,repr
  1. class Student():
  2.     def __init__(self, name, age):
  3.         self.name = name
  4.         self.age = age
  5.     """
  6.         1. 打印对象的时候,输出对象的时候会自动触发类中得__str__方法
  7.         2. 返回值必须是字符串形式
  8.         3. 如果它跟__repr__方法同时存在,__str__的优先级更高
  9.     """
  10.     def __str__(self): # 这个用的是最多的
  11.         print('str')
  12.         return 'from str'
  13.     def __repr__(self):
  14.         print('repr')
  15.         return 'from repr'
  16. wqe=Student('qwe',12)
  17. print(wqe)#str  from str
  18. # print('repr:', repr(wqe))
  19. print('str:', str(wqe))#str  str: from str
复制代码
del
  1. class MySQL:
  2.     def __init__(self, ip, port):
  3.         self.ip = ip
  4.         self.port = port
  5.         self.f = open('a.txt', 'w')
  6.     """
  7.     1.当你删除对象的时候会触发__del__的执行
  8.     2. 当整个脚本的程序都执行完毕的时候,也会触发__del__的执行
  9.     3. 一般用在用来在对象被删除时自动触发回收系统资源的操作
  10.     """
  11.     def __del__(self):
  12.         print('from _del')
  13.         self.f.close()
  14. mysql = MySQL('127.0.0.1', 3306)
复制代码
issubclass方法用于判断参数 class 是否是类型参数 classinfo 的子类
  1. class Foo:
  2.     pass
  3. class Bar(Foo):
  4.     pass
  5. class Bar1():
  6.     pass
  7. print(issubclass(Bar1, Foo))
复制代码
__doc__注释无法继承
  1. class Foo:
  2.     """
  3.     '我是描述信息asdasd'
  4.     '我是描述信息asdasd'
  5.     '我是描述信息asdasd'
  6.     """
  7.     pass
  8. class Bar(Foo):
  9.     pass
  10. print(Foo.__doc__)
  11.     # '我是描述信息asdasd'
  12.     # '我是描述信息asdasd'
  13.     # '我是描述信息asdasd'
  14. print(Bar.__doc__)
  15. #None
复制代码
enter和exit     上下文管理器with原理
  1. class Open:
  2.     def __init__(self, name):
  3.         self.name = name
  4.     def __enter__(self):
  5.         print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
  6.         # return self
  7.     def __exit__(self, exc_type, exc_val, exc_tb):
  8.         print('with中代码块执行完毕时执行我啊')
  9. """with它可以用在很多地方,但是,出现with语句后面的对象中得类必须要声明__enter__和__exit__"""
  10. with Open('a.txt') as f:
  11.     print('=====>执行代码块')
  12.     print('=====>执行代码块')
  13.     print('=====>执行代码块')
  14.     print('=====>执行代码块')
  15.     print('=====>执行代码块')
  16.     # print(f,f.name)
  17.    
复制代码
  1. 简答题:先聊聊with 的用法? 问with上下文管理协议的执行原理? 为什么打开文件只会可以自动关闭?请说出原因
  2. class Open:
  3.     def __init__(self, name):
  4.         self.name = name
  5.     def __enter__(self):
  6.         print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量')
  7.         # return self
  8.     def __exit__(self, exc_type, exc_val, exc_tb):
  9.         print('with中代码块执行完毕时执行我啊')
  10.         print(exc_type) # 异常类型
  11.         print(exc_val) # 异常值
  12.         print(exc_tb) # 追溯信息
  13.         return True # 如果你在这个方法里面返回了True,with代码块中出现了异常,就相当于没有出现异常
  14. """with它可以用在很多地方,但是,出现with语句后面的对象中得类必须要声明__enter__和__exit__"""
  15. # with Open('a.txt') as f:
  16. #     print('=====>执行代码块')
  17. #     print('=====>执行代码块')
  18. #     print('=====>执行代码块')
  19. #     print('=====>执行代码块')
  20. #     print('=====>执行代码块')
  21. #     # print(f,f.name)
  22. """如果with代码块中出现了异常,则with语句之后的代码都不能正常执行"""
  23. with Open('a.txt') as f:
  24.     print('=====>执行代码块')
  25.     raise AttributeError('***着火啦,救火啊***') # 抛出异常,主动报错
  26. print('0'*100) #------------------------------->不会执行
复制代码
setattr 设置 ,delattr 删除,getattr查看

点语法
  1. __setattr__,__delattr__,__getattr__
  2. class Foo:
  3.     x=1
  4.     def __init__(self,y):
  5.         self.y=y
  6.     """当你找的属性不存在的时候,会触发__getattr__,但是必须是点语法的时候才会"""
  7.     def __getattr__(self, item):
  8.         print('----> from getattr:你找的属性不存在')
  9.     def __setattr__(self, key, value):
  10.         print('----> from setattr')
  11.         # self.key=value # self.a=20
  12.         # self.key=value #这就无限递归了,你好好想想
  13.         self.__dict__[key]=value #应该使用它
  14.     def __delattr__(self, item):
  15.         print('----> from delattr')
  16.         # del self.item #无限递归了
  17.         self.__dict__.pop(item)
  18. obj=Foo(10)
  19. # obj.z
  20. obj.a=20
  21. print(obj.a)
  22. del obj.a
复制代码
setitem,getitem,delitem__

中括号取值时
  1. __setitem__,__getitem,__delitem__
  2. class Foo:
  3.     def __init__(self, name):
  4.         self.name = name
  5.     """当你通过中括号获取对象的属性的时候,会自动触发__getitem__"""
  6.     def __getitem__(self, item):
  7.         print('__getitem__')
  8.         print(self.__dict__[item])
  9.     def __setitem__(self, key, value):
  10.         # key:age
  11.         # value:18
  12.         print('__setitem__')
  13.         self.__dict__[key] = value
  14.         #  self.__dict__['age'] = 18
  15.     def __delitem__(self, key):
  16.         print('del obj[key]时,我执行')
  17.         self.__dict__.pop(key)
  18.         pass
  19.     # def __delattr__(self, item):
  20.     #     print('del obj.key时,我执行')
  21.     #     self.__dict__.pop(item)
  22. obj=Foo('tom')
  23. # print(obj.name)
  24. # obj['name']
  25. obj['age'] = 18
  26. # obj.age=18
  27. print(obj.age)
  28. del obj['age']
复制代码
call
  1. class Foo:
  2.     def __init__(self):
  3.         pass
  4.     #### 当对象加括号的时候会触发__call__的执行
  5.     def __call__(self, *args, **kwargs):
  6.         print('__call__',*args)
  7. obj=Foo()
  8. print(obj)#<__main__.Foo object at 0x000002CCFDE2BF70>
  9. obj('qe')#__call__ qe
复制代码
来源:https://www.cnblogs.com/zhangfanshixiaobai/p/17755797.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具