面向对象高级

image

组合

组合和继承一样也是用来解决类与类之间的冗余问题

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

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 直译的叫法,在程序中用来表示代码执行过程中所处的前后环境。上下文管理器中有 enterexit 两个方法,以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里一切皆对象,所以反射方法不止可以用在对象身上,也可以用在类,甚至模块上。

posted @ 2021-12-07 15:37  JudyJU  阅读(45)  评论(2)    收藏  举报