python面向对象三大特性之封装

发布时间 2024-01-05 09:21:40作者: -半城烟雨

python面向对象三大特性之封装

【一】什么是封装

  • 封装就是对具体对象的一种抽象
  • 简单理解就是将不想让别人看到的东西全部藏起来

【二】为什么要封装

  • 有些敏感数据,我们不想让其他的用户或者开发者看到
  • 所以我们就会选择进行封装也就是隐藏这部分不想被别人看到的内容

【三】如何封装

class Person:
    name = 'Tony'
    age = 18
    location = '上海周浦新区澄天伟业'
    _location = '上海周浦新区澄天伟业_'
    __location = '上海周浦新区澄天伟业__'

    def show_info(self):
        # 在类内部,隐藏起来的属性可以调用到
        print(self.location)
        print(self._location)
        print(self.__location)

    def _show_info(self):
        # 在类内部,隐藏起来的属性可以调用到
        print(self.location)
        print(self._location)
        print(self.__location)

    def __show_info(self):
        # 在类内部,隐藏起来的属性可以调用到
        print(self.location)
        print(self._location)
        print(self.__location)

    def main(self):
        self.show_info()
        self._show_info()
        self.__show_info()


p = Person()

# 【1】封装数据属性
# 在类外部,调用不到,两个 _ 及以上封装起来的属性
# print(p.location) # 上海陆家嘴汤臣一品
# print(p._location) # 上海陆家嘴汤臣一品_
# print(p.__location) #  'Person' object has no attribute '__location'. Did you mean: '_location'?

# 【2】封装函数属性
p.show_info()
p._show_info()
p.__show_info()

# 【3】总结
# 封装数据属性,在类内部,没有用 _ 或者用一个 _ 封装起来的属性,在类内部可以任意访问,在类外部(对象)也可以随意访问
# 封装数据属性,在类内部,用 __ 封装起来的属性,在类内部可以任意访问,在类外部(对象)不可以访问
# 封装函数属性,在类内部,没有用 _ 或者用一个 _ 封装起来的属性,在类内部可以任意访问,在类外部(对象)也可以随意访问
# 封装函数属性,在类内部,用 __ 封装起来的属性,在类内部可以任意访问,在类外部(对象)不可以访问

【1】封装数据属性

print(p.location) 
print(p._location) 
print(p.__location) 
上海周浦新区澄天伟业
上海周浦新区澄天伟业_
AttributeError: 'Person' object has no attribute '__location'. Did you mean: '_location'?

【2】封装函数属性

p.show_info()
p._show_info()
p.__show_info()
上海周浦新区澄天伟业
上海周浦新区澄天伟业_
上海周浦新区澄天伟业__

【3】总结

  • 封装数据属性,在类内部,没有用 _ 或者用一个 _ 封装起来的属性,在类内部可以任意访问,在类外部(对象)也可以随意访问
  • 封装数据属性,在类内部,用 __ 封装起来的属性,在类内部可以任意访问,在类外部(对象)不可以访问
  • 封装函数属性,在类内部,没有用 _ 或者用一个 _ 封装起来的属性,在类内部可以任意访问,在类外部(对象)也可以随意访问

【二】property装饰器

【1】什么是property

  • property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
  • @property装饰器为我们提供了一种以属性访问的方式来调用方法的方式

【2】例子

将一个类的函数定义成特性以后,对象再去使用的时候Foo.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

class Foo:
    def __init__(self,val):
        self.__NAME = val

    @property
    def name(self):
        print('触发property属性')
        return self.__NAME
    @name.setter
    def name(self,value):
        print('准备修改property属性')
        #判断是不是字符串类型
        if not isinstance(value, str):
                 raise TypeError('%s must be str' % value)
        self.__NAME = value
    @name.deleter
    def name(self):
        print(f'删除的时候调用了我')
        raise PermissionError('Can not delete')

p=Foo('Tony')
p.name='hope'
print(p.name)
del p.name
print(p.name)

【3】为什么要用property

  • 将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
  • 面向对象的封装有三种方式:
    • 【public】
      • 这种其实就是不封装,是对外公开的
    • 【protected】
      • 这种封装方式对外不公开
      • 但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
    • 【private】
      • 这种封装对谁都不公开
  • python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现