面向对象(四)
组合
组合就是一个对象有一个属性,该属性的值是另一个对象。
组合的目的也是为了解决类和类之间的代码冗余问题。
# 定义一个类 class Course: def __init__(self, name, learn_time): self.name = name self.learn_time = learn_time # 将类实例化成对象 course1 = Course('python', '6mon') # 定义另一个类 class Student: def __init__(self, name): self.name = name # 将对象绑定给属性 self.course = course1 # 实例化对象 stu = Student('tom') # 可以直接使用组合类的属性 print(stu.course.name) print(stu.course.learn_time) # 结果: # python # 6mon
在类与类之间没有明显继承关系又需要使用时,推荐使用组合。
面向对象的内置函数
内置函数__str()__
__str()__的作用是在打印对象时直接触发函数体代码并返回值。
需要注意的是,该函数的返回值必须是字符串类型,不然就报错。
class Student: school = 'SH' def __init__(self, name, age): self.name = name self.age = age # 在打印类时触发 def __str__(self): # 返回值必须是字符串类型 return 'name:%s' % self.name # 打印类 print(Student('tom', 18)) # 结果:name:tom
内置函数__del()__
__del()__会在程序执行完毕,内存释放之后才会触发。
class Student: school = 'SH' def __init__(self, name, age): self.name = name self.age = age # 在释放内存时触发 def __del__(self): print('执行__del__') # 实例化 stu = Student('tom', 18) print('end') # 结果: # end # 执行__del__
在平时__del()__没什么用处,但当程序结束时,python只会回收自己的内存空间,即用户态内存,而操作系统的资源则没有被回收,这就需要我们定制__del()__,在对象被删除前向操作系统发起关闭数据库链接或文件的系统调用,回收资源。
class Student: school = 'SH' def __init__(self, name, age): self.name = name self.age = age # 打开文件 self.f = open('a.txt', 'w') # 在释放内存时触发 def __del__(self): print('执行__del__') # 在释放内存的同时关闭文件 self.f.close() # 实例化 stu = Student('tom', 18) print('end') # 结果: # end # 执行__del__
内置函数__enter()__和__exit()__
使用with上下文管理协议的水触发__enter__和__exit。
在出现with时,首先触发__enter__,并将返回值赋给as之后的变量名。
在with程序执行完毕之后执行__exit__。
# 定义一个模拟open的类 class Open: def __init__(self, name): self.name = name # 出现with语句,触发__enter__ def __enter__(self): print('出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量') # 返回的值会付给as之后的变量名 return self.name # with中代码块执行完毕时执行__exit__ def __exit__(self, exc_type, exc_val, exc_tb): print('with中代码块执行完毕时执行我啊') # 使用with语句 with Open('a.txt') as f: print('=====>执行代码块') print(f) # 结果: # 出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量 # =====>执行代码块 # a.txt # with中代码块执行完毕时执行我啊
__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行。
内置函数__call()__
__call__的作用是在对象后加括号直接调用函数体代码。
class Foo: def __init__(self): pass # 对象加括号自动触发 def __call__(self, *args, **kwargs): print('__call__') obj = Foo() # 执行 __init__ # 一切皆对象 obj() # 结果 # __call__
反射
反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)。
1.getattr
通过字符串来调用方法或对象。
class Student: school = 'sh' def __init__(self, name, age): self.name = name self.age = age def func(self): print('from func') stu = Student('tom', 18) # 输出stu.name print(getattr(stu, 'name')) # 当属性不存在会输出默认值,如果都没有则报错 print(getattr(stu, 'name1', None)) # 表示方法 print(getattr(stu, 'func')) # 加括号调用方法 getattr(stu, 'func')() # 结果: # tom # None # <bound method Student.func of <__main__.Student object at 0x0000018B94C5BC50>> # from func
getattr还可以用于调用模块中的方法。
import time getattr(time, 'sleep')(2)
2.setattr
通过字符串来添加属性。
class Student: school = 'sh' def __init__(self, name, age): self.name = name self.age = age def func(self): print('from func') stu = Student('tom', 18) # 通过字符串添加属性 setattr(stu, 'a', 123) print(stu.__dict__) # 结果 # {'name': 'tom', 'age': 18, 'a': 123}
3.delattr
通过字符串来删除元素。
class Student: school = 'sh' def __init__(self, name, age): self.name = name self.age = age def func(self): print('from func') stu = Student('tom', 18) # 通过字符串来删除元素 delattr(stu, 'name') print(stu.__dict__) # 结果 # {'age': 18}
4.hasattr
通过字符串判断属性是否存在。
class Student: school = 'sh' def __init__(self, name, age): self.name = name self.age = age def func(self): print('from func') stu = Student('tom', 18) # 通过字符串判断属性是否存在 print(hasattr(stu, 'name')) # 结果:True
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通