面向对象之封装

一、面向对象的精髓

  精髓就是将数据和处理数据的代码绑定成了一个对象,只要获取到对象,相应的数据和方法都有了。

 1 #1、在没有学习类这个概念时,数据与功能是分离的
 2 def exc1(host,port,db,charset,sql):
 3     conn=connect(host,port,db,charset)
 4     conn.execute(sql)
 5     return 123
 6 
 7 
 8 def exc2(host,port,db,charset,proc_name):
 9     conn=connect(host,port,db,charset)
10     conn.call_proc(proc_name)
11     return 123
12 
13 
14 def exc2(host,port,db,charset,proc_name):
15     conn=connect(host,port,db,charset)
16     conn.call_proc(proc_name)
17     return 123
18 #每次调用都需要重复传入一堆参数
19 exc1('127.0.0.1',3306,'db1','utf8','select * from tb1;')
20 
21 exc2('127.0.0.1',3306,'db1','utf8','存储过程的名字')
22 
23 #2、使用面向对象 
24 class Mysql: 25 26 def __init__(self,host,port,db,charset): 27 self.host = host 28 self.port = port 29 self.db = db 30 self.charset = charset 31 32 def exc2(self,proc_name): 33 conn=connect(self.host,self.port,self.db,self.charset) 34 conn.call_proc(proc_name) 35 return 123 36 37 def exc1(self,sql): 38 conn=connect(self.host,self.port,self.db,self.charset) 39 conn.execute(sql) 40 return 123 41 42 43 my1 = Mysql("127.0.0.1",3306,"mydb","utf-8") 44 45 my1.exc1("select *from table1") 46 my1.exc2("名字")

二、组合

  1.什么是组合?

    组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象。

  2.为何要用组合?

    通过为某一个对象添加属性,属性的值是另外一个类的对象的方式,可以间接地将两个类关联/整合/组合到一起,从而减少类与类之间的代码冗余。

  3.如何用组合?

#学生老师系统中添加一个课程,学生可以查看他选修的课程,老师也可以查看他任课的课程
class OldboyPeople(object):
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex




class OldboyStudent(OldboyPeople):
    def __init__(self,name,age,sex,score=0):
        super().__init__(name,age,sex)
        self.score=score
        self.courses=[]

    def chose_courses(self):
        print("%s chose courses"%self.name)

    def show_courses(self):
        print("%s学生选修的课程:"%self.name)
        for i in self.courses:
            i.tell_info()



class OldschoolTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level):
        super(OldschoolTeacher, self).__init__(name,age,sex)
        self.level=level
        self.courses=[]

    def score(self):
        pass

    def show_courses(self):
        print("%s老师开课的课程:"%self.name)
        for i in self.courses:
            i.tell_info()

class Course(object):
    def __init__(self,c_name,c_price,c_period):
        self.c_name=c_name
        self.c_price=c_price
        self.c_period=c_period
    def tell_info(self):
        print("<课程:%s 价格:%s 周期:%s>"%(self.c_name,self.c_price,self.c_period))


python=Course("python全栈开发",17800,"6个月")
linux=Course("linux",16800,"5个月")

stu1=OldboyStudent("周冬",18,"")
stu2=OldboyStudent("赖正荣",28,"")
tea1=OldschoolTeacher("林海峰",18,"",10)
stu1.courses.append(python)
stu1.courses.append(linux)
tea1.courses.append(linux)
stu1.show_courses()
tea1.show_courses()
组合

三、封装

  1.什么是封装?

    封:将存放于名称空间中的名字给藏起来,这种隐藏对外不对内。

    装:往容器/名称空间中存名字

    在程序中封装指的是对外隐藏内部的实现细节,并对外部提供使用接口,从而严格控制对类中的属性的操作。

  2.为何要用封装?

    2.1可以提高安全性,不对外开放类内部的实现细节,同时也可以在封装时,在外部提供的接口中增加额外的逻辑判断,依次来提高安全性。

    2.2封装同时也是为了明确区分类的内部和外部。

    2.3封装函数的属性可以隔离复杂度。

# ATM 的取款功能
# 1.插入银行卡 2.输入密码 3.选择取款金额  4.取款

class ATM:
    def __insert_card(self):
        print("插入银行卡...")

    def __input_pwd(self):
        print("输入密码...")
    def __select_money(self):
        print("选择取款金额...")
    def withdraw(self):
        self.__insert_card()
        self.__input_pwd()
        self.__select_money()
        print("取款成功!....")

atm = ATM()

atm.withdraw() # 外部调用这个简单的接口 就能完成一系列复杂的操作
封装隔离复杂度的方法

  3.如何使用封装?

    在属性或者方法名称前,加上两个下划线,就可以将其设置为私有的。

class Student:
    def __init__(self,name,age,sex,id_card):
        self.name=name
        self.age=age
        self.sex=sex
        self.__id_card=id_card

    def show_id_card(self):
        print(self.__id_card)

stu1=Student("钟大俊",20,"","330133013302")
#print(stu1.id_card)  是访问不到的,因为已经进行了封装
#print(__stu1.id_card) 为什么用__开头也找不到呢?接下去看
#此时我们查看stu1中的所有属性,利用__dict__查看
print(stu1.__dict__)
#>>>:{'name': '钟大俊', 'age': 20, 'sex': '男', '_Student__id_card': '330133013302'}
#发现__stu1.id_card变成了_Student__id_card,原来封装的时候原来的属性名称发生了变形,且这个变形只在类的定义阶段才会发生。
#也就是说:
stu1.__score=90
print(stu1.__score)  #此时能访问到的,属性名不在定义阶段加上__时不会发生变形。
#>>>:90
封装的实质

  总结:

    1. __开头的属性实现的隐藏仅仅只是一种语法意义上的变形,并不会真的限制类外部的访问

    2. 该变形操作只在类定义阶段检测语法时发生一次,类定义阶段之后新增的__开头的属性并不会变形。

    3. 如果父类不想让子类覆盖自己的属性,可以在属性前加__开头

    

posted on 2018-12-17 21:18  黑粥  阅读(140)  评论(0编辑  收藏  举报

导航