面向对象高级

组合
组合和继承一样也是用来解决类与类之间的冗余问题
一、组合就是对象拥有一个属性,该属性的值就是另外一个对象
class People:
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Student(People):
def tell(self):
print('%s|%s|%s' % (self.name, self.age, self.gender))
class Teacher(People):
def __init__(self, name, age, gender, level):
super().__init__(name, age, gender)
self.level = level
print('%s|%s|%s|%s' % (self.name, self.age, self.gender, level))
class Course:
def __init__(self, course_name, course_price, course_period):
self.course_name = course_name
self.course_price = course_price
self.course_period = course_period
def tell(self):
print('课程价格:%s|课程名称:%s|课程周期:%s' % (self.course_price, self.course_name, self.course_period))
stu1 = Student('judy', 19, 'female')
python = Course('python', 19800, '6mons')
linux = Course('linux', 19000, '5mons')
stu1.course = [] # stu1相当于一个字典,给stu1这个对象加一个建值对
stu1.course.append(python) # stu1这个属性是course这个类的对象
stu1.course.append(linux)
for i in stu1.course: # 遍历得到对象,然后可以调用
i.tell()
面向对象的内置函数
一、打印对象时触发函数
# __str__
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
self.f = open('a.txt', 'r')
def __str__(self):
return '%s|%s' % (self.name, self.age)
obj = Student('judy', 18)
print(obj) #打印obj这个对象时,自动触发__str__
二、删除内容时触发的内置方法
# __del__
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
self.f = open('a.txt', 'r')
def __del__(self):
print('当删除属性或方法的时候触发执行')
obj = Student('judy', 18)
del obj.name
# 有两种方法会触发__del__运行
方式1:主动删除
方式2:程序结束后清理内存时
如上面代码的1处,程序结束后,会清理内存空间,但是文件不会关闭,此时就可以在__del__方法下面写上关闭文件的命令。
三、关于with上下文管理协议
with的执行原理
在文件操作时,并不是不需要写文件的关闭,而是文件的关闭操作在 with 的上下文管理器中的协议方法里已经写好了。当文件操作执行完成后, with语句会自动调用上下文管理器里的关闭语句来关闭文件资源。
上下文管理器
ContextManager ,上下文是 context 直译的叫法,在程序中用来表示代码执行过程中所处的前后环境。上下文管理器中有 enter 和 exit 两个方法,以with为例子,enter 方法会在执行 with 后面的语句时执行,一般用来处理操作前的内容。比如一些创建对象,初始化等;exit 方法会在 with 内的代码执行完毕后执行,一般用来处理一些善后收尾工作,比如文件的关闭,数据库的关闭等。
class Myopen:
def __init__(self, path, mode):
self.path = path
self.mode = mode
def __enter__(self):
print('代码执行到__enter__')
self.f = open(self.path, self.mode)
return self.f
def __exit__(self, exc_type, exc_val, exc_tb):
print('代码执行到__exit__')
self.f.close()
with Myopen('test.txt', 'w') as f:
f.write('hello,judy')
代码执行结果:
代码执行到__enter__
操作成功
代码执行到__exit__
文件写入操作执行完以后,自动调用了__exit__方法
__exit__方法的参数:
exc_type:异常类型
exc_va:异常值
exc_tb:异常回溯追踪
class Mycount:
def __init__(self, a, b):
self.a = a
self.b = b
def __enter__(self):
print('代码执行到__enter__')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('代码执行到__exit__')
if exc_type==None:
print('没问题')
else:
print('Type:',exc_type)
print('Value:', exc_val)
print('TraceBack:', exc_tb)
def my_div(self):
res=self.a/self.b
return res
with Mycount(1,0) as f:
print(f.my_div())
执行结果:
代码执行到__enter__
代码执行到__exit__
Type: <class 'ZeroDivisionError'>
Value: division by zero
TraceBack: <traceback object at 0x7fd42edeeb08>
四、对象加括号可以触发的方法
# __call__
如果一个对象定义了此方法,则该对象可以模拟函数的行为
class Foo:
def __call__(self, x):
print('找到x了 x:', x)
f = Foo()
f(1)
执行结果:
找到x了 x: 1
反射
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
self.f = open('a.txt', 'r')
def __str__(self):
return '%s|%s' % (self.name, self.age)
obj = Student('judy', 18)
print(hasattr(obj, 'name')) # 判断obj是否有这个属性
res = getattr(obj, 'name') #用字符串调用属性
print(res)
setattr(obj, 'name', 'mary') #用字符串更改属性
print(obj.name)
delattr(obj, 'name') #用字符串删除属性
有句话说,python里一切皆对象,所以反射方法不止可以用在对象身上,也可以用在类,甚至模块上。
浙公网安备 33010602011771号