面向对象4终

1. 组合

  1. 继承:满足什么是什么的关系,is-a 的关系。
  2. 组合:就是一个对象拥有一个属性,该属性的值是另外一个对象,继承是一把双刃剑🗡,并不是继承的越多越好。
    这种组合的关系,用大白话来说,就是嵌套,下面用示例学习常见的组合(嵌套)情景:

简单示例:

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()

image

posted @ 2021-12-07 16:14  Joshua_jiaxue  阅读(34)  评论(0编辑  收藏  举报