• Python面向对象编程(三)


    封装

    1.为什么要封装?

    封装就是要把数据属性和方法的具体实现细节隐藏起来,只提供一个接口。封装可以不用关心对象是如何构建的,其实在面向对象中,封装其实是最考验水平的

    2.封装包括数据的封装和函数的封装,数据的封装是为了保护隐私,函数的封装是为了隔离复杂度

    3.数据的封装就是在属性前面加一个__

    class People:
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.__salary=salary
    p=People('zhang',19,100000)
    print(p.name)#zhang
    print(p.age)#19
    print(p.__salary)#AttributeError: 'People' object has no attribute '__salary'

    咦,报错了,让我们打开对象的名称空间,看看发生了什么

    print(p.__dict__)#{'name': 'zhang', 'age': 19, '_People__salary': 100000}

    哦,原来python把__salary变形成了_People__salary,再来一遍

    print(p._People__salary)#100000

    所以,Python中并没有绝对的隐藏,只要你知道了上面这个,就无所谓隐藏了

    这些变形操作,只在类的定义阶段或者对象定义(实例化阶段)阶段发生

    虽然在外部无法直接访问加了__的属性,但是在类内部可以访问到,可以这么理解,在定义阶段,只要遇到__开头的,Python解释器自动识别为_类名__属性,所以在类内部是可以访问到的,这样的话,我们就可以搞一点小事情了

    先来看这个

    class A:
        def foo(self):
            print('from A foo')
            self.bar()
        def bar(self):
            print('from A bar')
    class B(A):
        def bar(self):
            print('from B bar')
    b=B()
    b.foo()  #from A foo
          #from B bar  别想多了,调用函数时别看定义位置,要看调用位置

    如果就是想调用父类的bar()函数呢?该怎么做

    class A:
        def foo(self):
            print('from A foo')
            self.__bar()
        def __bar(self):
            print('from A bar')
    class B(A):
        def __bar(self):
            print('from B bar')
    b=B()
    b.foo() #from A foo
            #from A bar  有没有感受到编程的美妙

    4.封装的应用

    1)不让外界看到我们的数据属性是怎么定义的,只能通过我们提供的接口,看到我们允许外界看到的内容

    class People:
        def __init__(self,name,age,height,weight,hobby):
            self.__name=name
            self.__age=age
            self.__height=height
            self.__weight=weight
            self._hobby=hobby
        def tell_info(self):
            print('''
            name:%s
            age:%s
            height:%s
            weeight:%s
            '''%(self.__name,self.__age,
                 self.__height,self.__weight))
    p=People('zhang',18,1.90,75,'read')
    p.tell_info()

    2)更常用的场景是,我们可以限制数据的类型,添加自己的逻辑以后再封装好给用户

        def tell_name(self):
            print(self.__name)
        #修改名字
        def set_name(self,new):
            if not isinstance(new,str):
                raise TypeError('名字必须是字符串类型')
            self.__name=new

    5.看我们上面的操作,用户查看名字的时候还得p.tell_name(),本来是个数据属性,却被我们搞得变成了一个函数,怎么伪装一下呢,就可以用到property这个装饰器

    class People:
        def __init__(self,name,age,height,weight,hobby):
            self.__name=name
            self.__age=age
            self.__height=height
            self.__weight=weight
            self._hobby=hobby
        @property
        def name(self):
            return self.__name
    p=People('zhang',18,1.90,75,'read')
    print(p.name)#zhang

    数据属性还应该有修改,删除操作

        @property
        def name(self):
            return self.__name
    
        #name已经被property修饰过,就有setter和deleter
        @name.setter
        def name(self,new):
            if not isinstance(new,str):
                raise TypeError('名字必须是字符串类型')
            self.__name=new
        @name.deleter
        def name(self):
            del self.__name
    p = People('zhang', 18, 1.90, 75, 'read')
    print(p.name)#zhang
    p.name='can'    #修改
    print(p.name)#can
    del p.name #删除
    print(p.name)#AttributeError: 'People' object has no attribute '_People__name'
  • 相关阅读:
    文件或目录损坏且无法读取的解决办法
    MP3/视频播放
    系统备份
    网线水晶头接法
    网站模板
    EasyNVR将如何能够把内网各种各样的监控摄像机对接到公网云平台
    EasyNVR将如何能够把内网各种各样的监控摄像机对接到公网云平台
    EasyPusher手机直播推送是如何实现后台直播推送的
    EasyPusher手机直播推送是如何实现后台直播推送的
    EasyDarwin开源流媒体服务器支持basic基本认证和digest摘要认证解析
  • 原文地址:https://www.cnblogs.com/zhang-can/p/7142544.html
Copyright © 2020-2023  润新知