封装的含义

封装是指将数据与具体操作的实现代码放在某个对象内部,使这些代码的实现细节不被外界发现,外界只能通过接口使用该对象,而不能通过任何形式修改对象内部

封装的目的有三个:保护隐私、保证稳定性、降低使用复杂度

基本使用

  1. class Student(object):
  2. __name = '这是隐藏的' # 在python中所以并没有真正的隐藏,而是自动转换成了特定的语法
  3. name = '这是没有隐藏的'
  4. def __init__(self):
  5. pass
  6. print(Student.__dict__)
  7. # '_Student__name': '这是隐藏的'
  8. obj = Student()
  9. print(obj.name)
  10. # 这是没有隐藏的
  11. print(obj.__name)
  12. # 报错
  13. # AttributeError: 'Student' object has no attribute '__name'
  14. # print(obj._Student__name) # 虽然也可以通过这个这方法访问到,但是我们这样写就是为了不要去直接访问,明白即可
  15. # 这是隐藏的
  16. # print(Student._Student__name) # 虽然也可以通过这个这方法访问到,但是我们这样写就是为了不要去直接访问,明白即可
  17. # 这是隐藏的

注意:

  • 封装的功能只在类定义阶段才能生效
  • 封装并不是绝对的,仅是做了语法上的变形而已
  • 虽然指定了封装的内部变形语法,但是也不能直接去访问,需要通过特定的通道(接口)去访问

开放接口

  1. class Student(object):
  2. __school = '清华大学'
  3. def __init__(self, name, age):
  4. self.__name = name
  5. self.__age = age
  6. # 开设一个访问学生数据的通道(接口)
  7. def check_info(self):
  8. print("""
  9. 学生姓名:%s
  10. 学生年龄:%s
  11. """ % (self.__name, self.__age))
  12. # 开设一个修改学生数据的通道(接口)
  13. def set_info(self, name, age):
  14. if len(name) == 0:
  15. print("用户不能为空")
  16. return
  17. if not isinstance(age, int):
  18. print("年龄必须是数字")
  19. return
  20. self.__name = name
  21. self.__age = age
  22. stu = Student('kevin', 22)
  23. stu.check_info()
  24. # 学生姓名: kevin
  25. # 学生年龄: 22
  26. stu.set_info('tony', 18)
  27. stu.check_info()
  28. # 学生姓名: tony
  29. # 学生年龄: 18
  30. stu.set_info('', 18)
  31. # 用户不能为空
  32. stu.set_info('kevin', '1')
  33. # 年龄必须是数字
  34. """
  35. 将数据隐藏起来就限制了类外部对数据的直接操作,然后类内应该提供相应的接口来允许类外部间接地操作数据,接口之上可以附加额外的逻辑来对数据的操作进行严格地控制,目的的是为了隔离复杂度,例如:ATM程序的取款功能,该功能有很多其他功能组成,比如插卡、身份认证、输入金额、打印小票、取钱等,而对使用者来说,只需要开发取款这个功能接口即可,其余功能也可以隐藏起来。
  36. """

property装饰器

property就是将方法伪装成数据

  1. class Num(object):
  2. def __init__(self, num_1, num_2):
  3. self.num_1 = num_1
  4. self.num_2 = num_2
  5. @property
  6. def res(self):
  7. return "%s乘%s,结果等于%s" % (self.num_1, self.num_2, self.num_1 * self.num_2)
  8. num = Num(9, 6)
  9. print(num.res) # 不写@property,调用应该是num.res(),写上@property少了括号,伪装成数据

扩展

property还提供设置和删除属性的功能

  1. class Student(object):
  2. def __init__(self, name):
  3. self.__name = name # 将属性隐藏起来
  4. @property
  5. def name(self):
  6. return self.__name # 将功能方法,伪装成数据
  7. @name.setter
  8. def name(self, value):
  9. if not isinstance(value, str):
  10. print("%s,必须是字符串" % value)
  11. return
  12. self.__name = value
  13. return
  14. @name.deleter
  15. def name(self):
  16. print("不能删除")
  17. stu = Student('kevin')
  18. print(stu.name)
  19. # kevin
  20. stu.name = 123
  21. print(stu.name)
  22. # kevin
  23. stu.name = 'tony'
  24. print(stu.name)
  25. # tony
  26. del stu.name
  27. # 不能删除