day26

今日所学:

封装

什么是封装

对外部隐藏内部的属性,以及实现细节,给外部提供使用的接口。       注意:封装有隐藏的意思,但不是单纯的隐藏

为什么封装

1,提高安全性。2,隔离复杂度

学习封装的目的,就是为了能够限制外界对内部的数据的访问。python中属性的权限有两种:

       1》公开的:没有 任何限制,谁都能访问

        2》私有的:只有当前类本身可以用

# 案例:怎样进行封装
class Student:
    def __init__(self,name,age,gender,id_card):
        self.name = name
        self.age = age
        self.gender = gender
        self.__id_car = id_card
    def show_id_card(self):               #进行封装,访问一个私有被封装的方法
        # 可以在这里添加额外的任何逻辑代码,来限制外部的访问
        print(self.__id_card)                #完成封装 封装的方法
stu1 = Student("rose",20,",man","1111111111111111111")
print(stu1.name)         #结果为 rose
# print(stu1.__id_card)      #这样访问不了id_card ,报错
print(Student.__id_card)       #这样可以访问,结果为rose,即只有当前类本身能够访问
stu1.show_id_card()              #结果为 rose
# ##########
# 封装属性:提现了安全性
class Student:
    def __init__(self, name, age, gender, id_card):
        self.name = name
        self.age = age
        self.gender = gender
        self.__id_card = id_card
    #     称之为访问器,生成器,即定义一个方法来访问被封装的属性,这个方法叫访问器
    def get_id_card(self):               #进行封装,访问一个私有被封装的方法
        # 可以在这里添加额外的任何逻辑代码,来限制外部的访问
        print(self.__id_card)
        return self.__id_card
        #修改被封装的属性         称之为设置器
    def set_id_card(self,new_id):         #从外界传入一个新的值
        #案例:身份证号码必须是字符串类型,长度必须是18位
        if isinstance(new_id, str) and len(new_id) ==18:
            self.__id_card = new_id
        else:
            print("身份证号码错误,必须是字符串,且长度必须为18")
        self.__id_car = new_id
stu1 = Student("rose", 20, ",man", "1111111111111111111")
stu1.show_id_card()
# stu1.set_id_card("22222222222222")
# stu1.show_id_card()
id = stu1.get_id_card()
print(id)
stu1.set_id_card(123)       #结果为:身份证号码错误,必须是字符串,且长度必须为18
stu1.set_id_card("123456789987654321")
print(stu1.get_id_card())          #结果为123456789987654321
#     总结:在set_id_card中可以增加限制,和满足你所需求的功能,对其封装的进行修改
#           同理。在get_id_card中也可以怎加限制,例如判断满足的条件,判断合法就访问,对其用户进行了限制
#           目的:是为了保证安全性。除了可以封装属性,还可以封装方法
# 封装方法:体现了隔离复杂度
class ATM:
    def withdraw(self):
        self.__user_auth()
        self.__input_money()
        self.__save_record()
    def __user_auth(self):
        print("请输入账号密码...")
    def __input_money(self):
        print('请输入取款金额,余额为10000元')
    def __save_record(self):
        print("记录流水")
atm = ATM()
atm.withdraw()
#     总结:1,什么样的方法应该被封装起来:
#            一个为内部提供支持方法,不应该让外界直接访问,就把它藏起来,如上例中的__user_auth
#如何封装的:封装原理
#    就是把名字做了修改,通过修改名字的方法,即变形
#    如何变形,就是在名称带有双下划线开头的变量名字前加了_类名  如_Person_id_card
#    注意:变形这个操作是在定义类的时候发生的,只发生一次,
#          后续再添加的带有双下划线的任何属性,都将不会变形
#什么时候应该封装属性:
#      如银行卡密码,这种属性就不能直接被外界使用,要封装起来
class Teacher:
    def __init__(self, name, age, salary):
        self.name = name
        self.age = age
        self.__salary = salary
    @property
    def get_salary(self):
        return self.__salary
    def set_salary(self, new_salary):
        self.__salary = new_salary
t =Teacher("fee",23,16000)
print(t.get_salary())
t.set_salary(20000)
print(t.get_salary())
print(t.name)
#   出现的问题:被封装的属性在访问时,需要调用方法,而普通属性直接点就ok
#              这样一来对于使用者而言,必须要知道访问的属性,是私有还是公开,
#             然后调用对象的方法比较麻烦的。此时,我们的目标是,让访问的私有属性
#              和访问普通属性的方式一致,这时候就需要property装饰器,就是将一个私有的伪装成共有的
class Teacher:
    def __init__(self, name, age, salary):
        self.name = name
        self.age = age
        self.__salary = salary
    @property     #用于访问私有属性的值   相当于getter
    def salary(self):
        return self.__salary
    @salary.setter    #用来设置私有属性的值,@上面那个被装饰的函数(注意)
    def salary(self, new_salary):
        self.__salary = new_salary
    @salary.deleter     #用来删除私有属性的值
    def salary(self, a):
        print(a)
t = Teacher("WWW",22,11111)
t.salary = 500
print(t.salary)
print(t.__dict__)
 #通常使用 @property来访问私有的,希望将私有属性变为普通属性访问

多态:

标准解释:多个不同类型对象,可以响应同一个方法,并且产生不同结果

1.增加了程序的灵活性

  以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)

2.增加了程序额可扩展性

  通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用  

比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同

import abcclass Animal(metaclass=abc.ABCMeta): #同一类事物:动物    @abc.abstractmethod    def talk(self):        pass

class People(Animal): #动物的形态之一:人    def talk(self):        print('say hello')

class Dog(Animal): #动物的形态之二:狗    def talk(self):        print('say wangwang')

class Pig(Animal): #动物的形态之三:猪    def talk(self):        print('say aoao')

常用的内置函数

# 类中的内置函数:
# 1__str__
class Person:
    # 将对象转成字符串的时候执行
    def __str__(self):
        print("str run")
        return "ffff"
p = Person()
# str(p)                  str run
# 在默认的object 中,不要方法也可以实现,可以自己定义,去覆盖原来的定义,想要实现自己的功能
# 再打印时,通过自定义的效果,返回值必须是字符串类型,该方法在object 中,子类可以覆盖该方法来进行自定义

反射

hasattr 判断是否存在某个属性
getattr 获取某个属性的值
setattr 新增或修改某个属性
delattr 删除某个属性
class MY_CMD:
    def dir(self):
        os.system("dir")
    def ipconfig(self):
        os.system("ipconfig")
cmd = MY_CMD()
while True:
    name = input("请输入要执行的功能:")
    if hasattr(cmd,name):
        method = getattr(cmd,name)
        print(method)
        method()
    else:
        print("sorry this method is not exists....!")
"""
直接写import 称之为静态导入  建立在一个基础上:提前已经知道有这个模块
动态导入  指的是  在需要的任何时候 通过指定字符串类型的包名称来导入需要的模块
import importlib
mk = importlib.import_module(m_name)
mk 即导入成功的模块
"""
该方式常用在框架中 因为框架设计者不可能提前预知后续需要的模块和类

 

原文地址:https://www.cnblogs.com/Fzhiyuan/p/10897079.html