千家信息网

Python面向对象中封装的概念是什么

发表于:2025-02-01 作者:千家信息网编辑
千家信息网最后更新 2025年02月01日,这篇文章将为大家详细讲解有关Python面向对象中封装的概念是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一 封装的概念封装其实在我们的生活中处处都是,如电视
千家信息网最后更新 2025年02月01日Python面向对象中封装的概念是什么

这篇文章将为大家详细讲解有关Python面向对象中封装的概念是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

一 封装的概念

封装其实在我们的生活中处处都是,如电视机,电脑,手机等物品。我们通常只能看到其外部的形状,以及使用他们提供的功能,并不能看到其内部复杂的硬件组成,这些都是封装好的,不能让我们看到,避免我们的一些"特殊"操作,使其不能正常工作。编程源于生活。在python中也有对对象的封装操作,使其对外只提供固定的访问模式,不能访问其内部的私有属性和私有方法。python中的封装,一般指的是对类属性,类方法的封装,即类属性私有化和类方法私有化,具体如下面的小结所讲。

二 _ 和__ 对属性和方法的私有化

1. 单下划线_

当类中的属性和方法以_ 单下划线开头时,即说明这是类的保护变量和保护方法,按照编码约定,是不希望被外部访问的。但如果你要进行访问,也不会报错。

如下:

class A():    #_ 声明是保护属性和保护方法    _name = '张三'    def __init__(self):        self._age = 23    def _method(self):        print("我叫{},今年{}岁".format(self._name, self._age))if __name__ == '__main__':    a = A()    #打印类A的dir    print(a.__dir__())    #访问保护变量和保护方法    print(a._name)    a._method()

输出结果:

>>>
['_age', '__module__', '_name', '__init__', '_method', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
张三
我叫张三,今年23岁

可以看出,以_单下划线开头的属性和方法其实在类外部是可以访问的,但是根据约定,当我们看见这样的属性和方法时,不应该在外部对其进行访问。

2. 双下划线__

上面以单下划线开头的属性和方法虽然是保护的,但是在外部还是可以访问的。而当你看到以双下划线__开头的属性和方法时,请记住它们是类的私有属性和私有方法,在类外以及子类中以常规访问类属性类方法的方法是无法访问的,也无法对其进行修改,如下

class B():    #__ 声明是私有化的    __name = '张三'    def __init__(self):        self.__age = 23        self.__luange = 'python'    def __method(self):        #私有方法        print("我叫{},今年{}岁,我喜欢{}。".format(self.__name, self.__age, self.__luange))    def fun(self):        #公有方法        print("this is a public method")  if __name__ == '__main__':    b = B()    #打印类B的dir    print(b.__dir__())    #访问类B的私有属性和私有方法    b.fun()    print(b.__name, b.__age, b.__luange)    b.__method()

输出结果:

>>>
['_B__age', '_B__luange', '__module__', '_B__name', '__init__', '_B__method', 'fun', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
this is a public method
Traceback (most recent call last):
File "C:/Users/admin/python-learning/python学习文件/python基础/python类封装.py", line 56, in
print(b.__name, b.__age, b.__luange)
AttributeError: 'B' object has no attribute '__name'

从结果可以看出,访问类B的公有方法fun()是正常输出的,但是当我们访问私有属性name时就抛错:类B没有name属性。上面单下划线时,我们打印类A的dir,可以看到类A的name属性和method方法在dir里面是下面这样的

上面我们也打印了类B的私有属性和私有方法,如下:

可以看到私有属性和私有方法都变成了_B__属性和_B__方法的形式,所以我们在上面以__ name或者name的形式去访问是报错的,其实我们如果以 类名(). _ 类名__ 属性(实例属性)或者类名. _ 类名__ 属性(类属性)的形式去访问,还是会访问成功的。如下

class B():    #__ 声明是私有化的    __name = '张三'    def __init__(self):        self.__age = 23        self.__luange = 'python'    def __method(self):        #私有方法        print("我叫{},今年{}岁,我喜欢{}。".format(self.__name, self.__age, self.__luange))    def fun(self):        #公有方法        print("this is a public method")if __name__ == '__main__':    b = B()    #打印类B的dir    print(b.__dir__())    #访问类B的私有属性和私有方法    b.fun()    print(B._B__name, b._B__age, b._B__luange)    b._B__method()

结果如下:

>>>
['_B__age', '_B__luange', '__module__', '_B__name', '__init__', '_B__method', 'fun', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
this is a public method
张三 23 python
我叫张三,今年23岁,我喜欢python。

3. 子类中访问父类的私有属性和私有方法

子类无法访问父类的私有属性和私有方法:

class B():    #__ 声明是私有化的    __name = '张三'    def __init__(self):        self.__age = 23        self.__luange = 'python'    def __method(self):        #私有方法        print("我叫{},今年{}岁,我喜欢{}。".format(self.__name, self.__age, self.__luange))    def fun(self):        #公有方法        print("this is a public method")class C(B):    def __init__(self):        super().__init__()    def fun1(self):        #访问父类B的私有属性和私有方法        print(self.__name, self.__age, self.__luange)        self.__method()if __name__ == '__main__':    c = C()    c.fun1()

输出结果:

>>>
AttributeError: 'C' object has no attribute '_C__name'
AttributeError: 'C' object has no attribute '_C__method'

可以看出子类也是无法访问父类的私有属性和私有方法的。

当子类中的的属性和方法与父类的私有属性,私有方法同名时,不会覆盖父类的私有属性和私有方法。

class B():    #__ 声明是私有化的    __name = '张三'    def __init__(self):        self.__age = 23        self.__luange = 'python'    def __method(self):        #私有方法        print("我叫{},今年{}岁,我喜欢{}。".format(self.__name, self.__age, self.__luange))    def fun(self):        #公有方法        print("this is a public method")class C(B):    __name = '李四'    def __init__(self):        super().__init__()        self.__age = 24        self.__luange = 'C++'    def fun1(self):        #访问父类B的私有属性和私有方法        print(self.__name, self.__age, self.__luange)        self.__method()    def __method(self):        #类C的私有方法,与父类方法同名,但不重写父类方法        print("我叫{},今年{}岁,我喜欢{}。".format(self.__name, self.__age, self.__luange))        #调用父类的私有方法        B()._B__method()if __name__ == '__main__':    c = C()    #访问类C的私有方法    c._C__method()

结果如下:

>>>
我叫李四,今年24岁,我喜欢C++。
我叫张三,今年23岁,我喜欢python。

可以看到,子类C并没有重写父类B的__method()方法。这是为什么呢?我们打印一下B和C的dir,如下:

>>>
['_B__age', '_B__luange', '_C__age', '_C__luange', 'fun1',
'_C__method', '__doc__', '_B__name', '_B__method', '_C__name', ...]

可以看到,在类C的dir中,父类B的私有属性和私有方法是以 _B__属性(方法)存在的,二类C自己的私有属性和私有方法是以_C__属性(方法)存在的,即类的私有属性和私有方法会以_类名_属性(方法)的形式存在dir中,所以当子类的属性和方法与父类的私有属性和私有方法同名时,并不会覆盖重写。

三 访问及修改类的私有属性和私有方法

类通过对属性和方法的私有化,可以对其起到封装保护作用。但是,当外部需要访问和改变时怎么办呢?就像电视机,电脑也会对外提供固定的接口。
上面,虽然我们可以通过类名(). _ 类名__ 属性(实例属性)或者类名. _ 类名__ 属性(类属性)的形式去访问类的私有属性和私有方法,但是这是违反编程规范的,不支持这么做,就像不会拆开电视机对其操作一样。

正确对类的私有属性和私有方法进行访问修改的一般有两种发方法,如下:

1. 自定义公有方法

class D():    __name = '张三'    def __init__(self):        self.__age = 23        self.__luange = 'python'    def __method(self):        print("我叫{},今年{}岁,我喜欢{}。".format(self.__name, self.__age, self.__luange))    def get_value(self):        return self.__name, self.__age, self.__luange    def get_method(self):        self.__method()    def set_value(self, name, age, luange):        self.__name, self.__age, self.__luange = name, age, luangeif __name__ == '__main__':    d = D()    #通过get_value方法访问私有属性    print(d.get_value())    #通过get_method方法访问私有方法    print('=' * 30)    d.get_method()    #通过set_value方法修改私有属性    print('='*30)    print(d.get_value())    d.set_value('王二麻子', 25, 'Linux')    print(d.get_value())    d.get_method()

输出结果:

>>>
('张三', 23, 'python')
==============================
我叫张三,今年23岁,我喜欢python。
==============================
('张三', 23, 'python')
('王二麻子', 25, 'Linux')
我叫王二麻子,今年25岁,我喜欢Linux。

可以看到,我们通过自定义的的get_value(),get_method()以及set_value()方法就实现了对私有属性和私有方法的访问和修改。

2. property

property一般有两个作用,如下:

  • 作为装饰器,@property 将类的方法转为只读的类属性

  • property 重新实现一个属性的 getter 和 setter 方法

来看看下面这个E类,如下:

class E():    __name = '张三'    def __init__(self):        self.__age = 23        self.__luange = 'python'    def __method(self):        print("我叫{},今年{}岁,我喜欢{}。".format(self.__name, self.__age, self.__luange))    def get_value(self):        return self.__name    def set_value(self, name):        self.__name = name    getValue = property(get_value, set_value)    @property    def get_method(self):        self.__method()if __name__ == '__main__':    e = E()    #访问    print(e.getValue)    e.get_method    #修改    e.getValue = '王二'    print(e.getValue)

结果:

>>>
张三
我叫张三,今年23岁,我喜欢python。
王二

可以看到,我们将get_valueset_value方法传入property后,类方法就转换成类属性,并赋值给getValue变量。此时e.getValue就是只读,即get_value方法,e.value = ‘王二’ 就是修改,即get_value方法。同一,通过@propert,将get_method方法,变成了属性。

下面property 重新实现一个属性的 getter 和 setter 方法,不同于上面的写法,较上面常用。

class E():    __name = '张三'    def __init__(self):        self.__age = 23        self.__luange = 'python'    def __method(self):        print("我叫{},今年{}岁,我喜欢{}。".format(self.__name, self.__age, self.__luange))    @property    def name(self):        return self.__name    @name.setter    def name(self, name):        self.__name = nameif __name__ == '__main__':    e = E()    #访问    print(e.name)    #修改    print("修改前:", e.name)    e.name = '隔壁老王'    print("修改后:", e.name)

输出结果:

>>>
张三
修改前: 张三
修改后: 隔壁老王

上面是首先把name方法送给propert装饰器进行装饰,然后调用装饰后的setter方法,即可实现对私有属性进行修改。

关于"Python面向对象中封装的概念是什么"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

方法 私有 属性 张三 我喜欢 封装 类名 结果 保护 下划线 子类 输出 形式 开头 对象 概念 变量 篇文章 这是 麻子 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 福建互联网养老软件开发系统 携程上海网络技术有限公司 数据库系统实验报告系统分析 静安区生态网络技术 网络安全危机愈演愈烈并逐步 软件开发是最难的吗 煎饼网络技术 拉勾 还原数据库的纪录哪里查看 反间谍小说软件开发 成都市网络安全员总决赛 数据库集群的启动顺序 网络安全宫保鸡丁 宝塔服务器怎么使用永久的 如何查看一个数据库有几个表 江苏东趣网络技术服务 公安采集血液数据库系统啥原理 9亿tv服务器关停还有啥办法 数据库升级技术标书 利用计算机技术网络技术 mt管理器模拟服务器 软件开发费要记入哪个科目 服务器ic灯是什么意思 药品标准物质查询数据库 网络安全周主题知识 逃离塔克夫服务器名字 云服务器ip绑定域名 安联财险 网络安全险 中等职业网络安全技术书 软件开发周期是什么 如何停止服务器管理器的任务
0