Python面向对象——封装

内容回顾

上节课复习:
    1、编程范式/思想
        面向过程
            介绍:
                核心是"过程"二字
                过程就是"流水线"
                过程终极奥义是将程序流程化


            优点:
                1、将程序流程化,进而程序的设计会变得简单化

            缺点:
                1、可扩展性差

        面向对象
             介绍:
                核心是"对象"二字
                对象就是"容器",用来盛放数据与功能
                对象终极奥义是将程序进行高度整合

            优点:
                1、提升程序的解耦合程度,进而增强程序的可扩展性

            缺点:
                1、设计复杂

    2、面向对象编程
        一:现实生活中:
            1、先找出现实生活中的对象
            2、然后总结归纳出现实生活中的类

        二:程序中:
        1、先定义程序中的类
        2、后调用类产生程序中对象(调用类的过程又称之为实例化)
class Student:
    school = 'Oldboy'

    # 该方法会在对象产生之后自动执行,专门为对象进行初始化操作,可以有任意代码,但一定不能返回非None的值

    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

    def choose(self):
        print('%s is choosing a course' % self.name)


stu1 = Student('李建刚', '男', 28)
stu2 = Student('王大力', '女', 18)

1、类中的数据属性
print(id(Student.school))
print(id(stu1.school))
print(id(stu2.school))

Student.school = 1111111
stu1.school = 1111111
print(stu1.school)
print(stu2.school)

2、类中的函数属性
print(Student.choose)
Student.choose(stu1)  # 类可以用,但就是一个普通函数
stu1.choose()
stu2.choose()

print(Student.__dict__)
print(stu1.__dict__)
print(stu2.__dict__)

Student.xxx = 1
print(Student.xxx)
stu1.age = 20
stu1.yyy = 30

print(stu1.xxx)
stu1.xxx = 3333333333
print(stu1.__dict__)
print(stu1.xxx)
print(stu2.xxx)

l = []  # l=list([])
print(type(l))

print(type(stu1))

封装

一:封装介绍 封装是面向对象三大特性最核心的一个特性 封装 < – >整合
二、将封装的属性进行隐藏操作
1、如何隐藏:在属性名前加__前缀, 就会实现一个对外隐藏属性效果
三、该隐藏需要注意的问题:
I: 在类外部无法直接访问双下滑线开头的属性,但知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如Foo._A__N, 所以说这种操作并没有严格意义上地限制外部访问,仅仅只是一种语法意义上的变形。

class Foo:
    __x = 1  # _Foo__x

    def __f1(self):  # _Foo__f1
        print('from test')


# print(Foo.__dict__) 打印出所有的变量
# print(Foo._Foo__x)
# print(Foo._Foo__f1)

II:这种隐藏对外不对内, 因为__开头的属性会在检查类体代码语法时统一发生变形

class Foo:
    __x = 1  # _Foo__x = 1

    def __f1(self):  # _Foo__f1
        print('from test')

    def f2(self):
        print(self.__x)  # print(self._Foo__x)
        print(self.__f1)  # print(self._Foo__f1)


print(Foo.__x)
print(Foo.__f1)
obj = Foo()
obj.f2()

III: 这种变形操作只在检查类体语法的时候发生一次,之后定义的__开头的属性都不会变形

class Foo:
    __x = 1  # _Foo__x = 1

    def __f1(self):  # _Foo__f1
        print('from test')

    def f2(self):
        print(self.__x)  # print(self._Foo__x)
        print(self.__f1)  # print(self._Foo__f1)


Foo.__y = 3
print(Foo.__dict__)
print(Foo.__y)


class Foo:
    __x = 1  # _Foo__x = 1

    def __init__(self, name, age):
        self.__name = name
        self.__age = age


obj = Foo('egon', 18)
print(obj.__dict__)
print(obj.name, obj.age)

为何要隐藏?

I、隐藏数据属性"将数据隐藏起来就限制了类外部对数据的直接操作,然后类内应该提供相应的接口来允许类外部间接地操作数据,接口之上可以附加额外的逻辑来对数据的操作进行严格地控制

class People:
    def __init__(self, name):
        self.__name = name

    def get_name(self):
        # 通过该接口就可以间接地访问到名字属性
        # print('小垃圾,不让看')
        print(self.__name)

    def set_name(self, val):
        if type(val) is not str:
            print('小垃圾,必须传字符串类型')
            return
        self.__name = val


# 使用者:王鹏
obj = People('egon')
print(obj.name)  # 无法直接用名字属性
obj.set_name('EGON')
obj.set_name(123123123)
obj.get_name()
# II、隐藏函数/方法属性:目的的是为了隔离复杂度

作业

# 整合->解耦合->扩展性增强

class School:
    school_name = 'OLDBOY'

    def __init__(self, nickname, addr):
        self.nickname = nickname
        self.addr = addr
        self.classes = []

    def related_class(self, class_obj):
        # self.classes.append(班级名字)
        # self.classes.append(class_name)
        self.classes.append(class_obj)

    def tell_class(self):  # 改
        # 打印的班级的名字
        print(self.nickname.center(60, '='))
        # 打印班级开设的课程信息
        for class_obj in self.classes:
            class_obj.tell_course()


# # 一:学校
# #1、创建校区
school_obj1 = School('老男孩魔都校区', '上海')
school_obj2 = School('老男孩帝都校区', '北京')

# 2、为学校开设班级
# 上海校区开了:脱产14期,上海校区开了脱产15期
school_obj1.related_class("脱产14期")
school_obj1.related_class("脱产15期")

# 北京校区开了:脱产29期
school_obj2.related_class("脱产29期")

# 3、查看每个校区开设的班级
school_obj1.tell_class()
school_obj2.tell_class()


class Class:
    def __init__(self, name):
        self.name = name
        self.course = None

    def related_course(self, course_obj):
        # self.course = course_name
        self.course = course_obj

    def tell_course(self):
        print('%s' % self.name, end=" ")
        self.course.tell_info()  # 打印课程的详细信息


# 二:班级
# 1、创建班级
class_obj1 = Class('脱产14期')
class_obj2 = Class('脱产15期')
class_obj3 = Class('脱产29期')

# 2、为班级关联一个课程
class_obj1.related_course('python全栈开发')
class_obj2.related_course('linux运维')
class_obj3.related_course('python全栈开发')

# 3、查看班级开设的课程信息
class_obj1.tell_course()
class_obj2.tell_course()
class_obj3.tell_course()

# 4、为学校开设班级
# 上海校区开了:脱产14期,上海校区开了脱产15期
school_obj1.related_class(class_obj1)
school_obj1.related_class(class_obj2)

# 北京校区开了:脱产29期
school_obj2.related_class(class_obj3)


school_obj1.tell_class()
school_obj2.tell_class()


class Course:
    def __init__(self, name, period, price):
        self.name = name
        self.period = period
        self.price = price

    def tell_info(self):
        print('<课程名:%s 周期:%s 价钱:%s>' % (self.name, self.period, self.price))


# 三:课程
# 1、创建课程
course_obj1 = Course('python全栈开发', '6mons', 20000)
course_obj2 = Course('linux运维', '5mons', 18000)

# 2、查看课程的详细信息
course_obj1.tell_info()
course_obj2.tell_info()

# 3、为班级关联课程对象
class_obj1.related_course(course_obj1)
class_obj2.related_course(course_obj2)
class_obj3.related_course(course_obj1)

class_obj1.tell_course()
class_obj2.tell_course()
class_obj3.tell_course()

school_obj1.tell_class()
school_obj2.tell_class()

class Student:
    pass


1、练习上课作业讲解的面向对象代码,明天默写
2、基于上课作业讲解的面向对象代码,扩写Student类
3、加入序列化与反序列化操作
4、对象之间的关联采用id5、可以通过id找到对应的文件,然后从文件中反序列化出执行的学校、班级、课程、学生对象
posted @ 2022-03-03 12:48  喝茶看猴戏  阅读(27)  评论(0)    收藏  举报  来源