面向对象4终
1. 组合
- 继承:满足什么是什么的关系,is-a 的关系。
- 组合:就是一个对象拥有一个属性,该属性的值是另外一个对象,继承是一把双刃剑🗡,并不是继承的越多越好。
这种组合的关系,用大白话来说,就是嵌套,下面用示例学习常见的组合(嵌套)情景:
简单示例:
class Foo(object):
def __init__(self, m):
self.m = m
class Bar(object):
def __init__(self, n):
self.n = n
obj = Foo(10)
obj1 = Bar(20)
obj.x = obj1
print(obj.__dict__)
# obj 此时就是一个超级对象
print(obj.x.n) # 20
print(obj1.n) # 20
情景一:
class Student(object):
"""学生类"""
def __init__(self, name, age):
self.name = name
self.age = age
def message(self):
data = '我是一名学习,我叫{},我今年{}'.format(self.name, self.age)
print(data)
s1 = Student('jack', 18)
s2 = Student('jason', 22)
s3 = Student('昊天', 33)
class Classes(object):
"""班级类"""
def __init__(self, title):
self.title = title
self.student_list = []
def add_student(self, stu_object):
self.student_list.append(stu_object)
def add_students(self, stu_obj_list):
for stu in stu_obj_list:
self.add_student(stu)
def show_members(self):
for item in self.student_list:
print(item)
item.message()
item.name()
c1 = Classes('三年二班')
c1.add_atudent(s1)
c1.add_students([s2, s3])
print(c1.title) # 三年二班
print(c1.student_list) # 对象列表
c1.show_members()
情景二:
class Student(object):
"""学生类"""
def __init__(self, name, age, class_object):
self.name = name
self.age = age
self.class_object = class_object
def message(self):
data = '我是一名{}班的学生,我叫:{},今年{}岁'.format(self.class_object, self.name, self.age)
print(data)
class Classes(object):
"""班级类"""
def __init__(self, title):
self.title = title
c1 = Classes('python全栈')
c2 = Classes('Linux云计算')
user_object_list = [
Student('jack', 22, c1),
Student('tom', 33, c1),
Student('昊天', 28, c2)
]
for obj in user_object_list:
print(obj.name, obj.age, obj.class_object)
情景三:
class Student(object):
"""学生类"""
def __init__(self,name,age,class_object):
self.name = name
self.age = age
self.class_object = class_object
def message(self):
data = '我是一名{}的学生,我叫:{},今年{}岁'.format(self.class_object.title, self.name, self.age)
print(data)
class Classes(object):
"""班级类"""
def __init__(self, title, school_object):
self.title = title
self.school_object = school_object
class School(object):
"""学校类"""
def __init__(self, name):
self.name = name
s1 = School('BJ')
s2 = School('SH')
c1 = Classes('python全栈', s1)
c2 = Classes('linux云计算', s2)
user_object_list = [
Student('jason', 19, c1),
Student('jack', 20, c1),
Student('joshua', 28, c2)
]
for obj in user_object_list:
print(obj)
print(user_object_list[0].class_object.school_object.name)
2. 面向对象的内置方法(魔术方法)
# 1. __init__()初始化方法
class Foo(object):
def __init__(self,name):
self.name = name
obj = Foo('jason')
# 2. __new__() 构造方法(很少用,但是很重要,面试和后面会用到)
```python
class Foo(object):
def __init__(self, name):
print('第二步:初始化对象,在空对象中创建数据')
self.name = name
def __new__(cls, *args, **kwargs):
print('第一步:先创建空对象并返回')
return object.__new__(cls)
# 一般我们会省略不写,但是在内部仍然会执行new方法,
# Foo里面没有会去他的父类object中去找。
obj = Foo('alex')
# 3. __str__()
class Student():
school = 'SH'
def __init__(self,name):
self.name = name
def tell(self):
print('name:{}'.format(self.name))
def __str__(self):
# 次方法里面必须返回一个字符串
return self.name
stu = Student('ly')
# 打印对象的时候自动触发的函数__str__
print(stu)
data = str(obj)
print(data)
# 4. __del__()
class Student(object):
school = 'SH'
def __init__(self,name,age):
self.name = name
self.age = age
self.f = open('a.txt', 'w')
# 1.手动执行del
# 2.程序执行完毕,触发del
def __del__(self):
print('__del__')
self.f.close()
stu = Student('ly')
del stu.name
print('end----------')
# 5. __enter__() with上下文管理系统就涉及这个
# 6. __exit__() 他们成对出现,面试可能出现
class Open(object):
def __init__(self, name):
self.name = name
def __enter__(self):
print('出现with语句,对象的__enter__方法被触发,有返回值则赋值给as声明的变量')
return self
# 括号中的分别代表:异常类型,异常值,追溯信息
def __exit__(self,exc_type,exc_val,exc_tb):
print('with中代码块执行完毕时执行这里')
with Open('a.txt', 'w') as f:
print('=====执行代码块')
print(f)
# 7. __call__()
class Foo(object):
def __init__(self):
pass
# 对象+()括号自动触发call方法
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行__init__
# 一切皆对象,对象加括号执行call方法
obj()
python中统一类与类型
a = [1,2,3]
b = list([1,2,34,5])
a.append(4) # == list.append(a, 4)
list.append(a, 55)
print(a)
3. 反射(掌握4个方法)
反射,提供了一种更加灵活的方式让你可以实现 去 对象中操作成员(就是以字符串的形式去对象中进行成员的操作)。
class Student(object):
def __init__(self, name):
self.name = name
def funt(self):
print('from func')
stu = Student('ly')
print(stu.name)
# 1. getattr
print(getattr(stu, 'name')) #== stu.name
print(getattr(stu, 'nameee', None))
# 必须掌握的
getattr(stu, 'func')()
"""重点,以后看源码用得到!!!"""
# 2. setattr
setattr(stu, 'age', 22)
print(stu.__dict__)
# 3. hasattr
print(hasattr(stu, 'name')) # True
# 4. delattr
delattr(stu, 'name')
print(stu.__dict__)
# 在类中
print(getattr(Student, 'school'))
# 模块中
import time
time.sleep(2)
getattr(time, 'sleep')(2)
__import__('time') # == import time
"""在python中想要导入一个模块,也可以通过字符串的形式导入"""
from importlib import import_module
m = import_module('random')
v1 = m.randint(1,10)
面试题
补充代码,实现如下功能
class Context:
def do_something(self):
print('内部执行')
with Context() as ctx:
print('外部执行')
ctx.do_something()