面向对象(四)

组合

  组合就是一个对象有一个属性,该属性的值是另一个对象。

  组合的目的也是为了解决类和类之间的代码冗余问题。

复制代码
# 定义一个类
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
复制代码

 

posted @   临江沂水  阅读(31)  评论(0编辑  收藏  举报
编辑推荐:
· 基于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最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示