Python面向对象中的封装详情

目录
  • 一封装的概念
  • 二_和__对属性和方法的私有化
    • 1.单下划线_
    • 2.双下划线__
    • 3.子类中访问父类的私有属性和私有方法
  • 三访问及修改类的私有属性和私有方法
    • 1.自定义公有方法
    • 2.property

一 封装的概念

封装其实在我们的生活中处处都是,如电视机,电脑,手机等物品。我们通常只能看到其外部的形状,以及使用他们提供的功能,并不能看到其内部复杂的硬件组成,这些都是封装好的,不能让我们看到,避免我们的一些“特殊”操作,使其不能正常工作。编程源于生活。在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 <module>
    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, luange

if __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 = name

if __name__ == '__main__':
    e = E()
    #访问
    print(e.name)
    #修改
    print("修改前:", e.name)
    e.name = '隔壁老王'
    print("修改后:", e.name)

输出结果:

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

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

到此这篇关于Python面向对象中的封装详情的文章就介绍到这了,更多相关Python封装内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python面向对象编程之类的封装

    目录 1.封装的理解 2.私有类属性.公开类属性.私有实例属性和公开实例属性 2.1 公开类属性 2.2 私有类属性 2.3 公开实例属性 2.4 私有实例属性 2.5 私有属性不一定真的私有 3.私有方法和公开方法 4.类的保留属性 5.类的保留方法 1.封装的理解 封装(Encapsulation):属性和方法的抽象 属性的抽象:对类的属性(变量)进行定义.隔离和保护 分为私有属性和公开属性: 私有属性:只能在类内部访问 公开属性:可以通过类.对象名访问 可以选择公开或隐藏属性,隐藏属性的内

  • Python面向对象封装继承和多态示例讲解

    面向对象的三大特征:封装,继承,多态 1.封装: 提高程序的安全性 将数据(属性)和行为(方法)包装到类对象中,在方法内部对属性进行对象的外部调用方法. 这样无需关心内部的具体实现. 在python中没有专门的修饰符用于属性的私有,如果属性不希望被访问,前面使用两个下划线 2.继承: 提高代码的复用性 3.提高程序的可拓展性和可 维护性. 1. 封装 我们来看看私有方式的使用: # 作者:互联网老辛 # 开发时间:2021/4/4/0004 22:11 class Student: def __

  • Python面向对象封装操作案例详解 II

    本文实例讲述了Python面向对象封装操作.分享给大家供大家参考,具体如下: 目标 士兵突击案例 身份运算符 封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 -- 将 属性 和 方法 封装 到一个抽象的 类 中 外界 使用 类 创建 对象,然后 让对象调用方法 对象方法的细节 都被 封装 在 类的内部 一个对象的 属性 可以是 另外一个类创建的对象 01. 士兵突击 需求 士兵 许三多 有一把 AK47 士兵 可以 开火 枪 能够 发射 子弹 枪 装填 装填子弹 -- 增加子弹数量

  • Python面向对象编程之封装的艺术你了解吗

    目录 1.面向对象编程 1.1OOP特点 1.2OOP基本概念 2.Python实现OOP 2.1分析问题 2.2类设计语法 2.3创建对象语法 3.OOP的封装性 3.1广义角度:无处不封装 封装的优点! 3.2狭义角度:保证内部数据的完整性 实施流程: 4.总结 1. 面向对象编程 OOP ( Object Oriented Programming) 即面向对象编程. 面向对象编程是一种 编码思想 ,或是一种 代码组织方式 .如同编辑文章时,可以选择 分段.分节 的方式让文章看起来有层次.更

  • python 面向对象之class和封装

    # 封装 # Python并没有真正的私有化支持,但可用下划线得到伪私有 访问私有变量:实例._类名__变量名 访问私有方法:实例._类名__方法名() class Wife02(): def __init__(self,name,age,sex): # 负责对象的初始化 self.set_name(name) self.set_age(age) self.set_sex(sex) def set_name(self,value): if isinstance(value,str): # 数据类

  • Python面向对象三大特征 封装、继承、多态

    目录 1.封装 1.1 私有属性和私有方法 2.继承 2.1 方法的重写 2.2 在子类方法中调用父类方法 2.3 多继承 2.4 新式类和经典类 3.多态 1.封装 封装: 根据 职责 将 属性 和 方法 封装到一个 抽象的类 中将数据(属性)和行为(方法)包装到类对象中.在方法内部对属性进行操作,在类对象的外部调用方法.这样无需关心方法 内部的具体实现,从而隔离了复杂度 封装是面向对象编程的一大特点 面向对象编程的第一步.将属性和方法封装到一个抽象的类中 外界使用类创建对象,然后让对象调用方

  • Python面向对象中的封装详情

    目录 一封装的概念 二_和__对属性和方法的私有化 1.单下划线_ 2.双下划线__ 3.子类中访问父类的私有属性和私有方法 三访问及修改类的私有属性和私有方法 1.自定义公有方法 2.property 一 封装的概念 封装其实在我们的生活中处处都是,如电视机,电脑,手机等物品.我们通常只能看到其外部的形状,以及使用他们提供的功能,并不能看到其内部复杂的硬件组成,这些都是封装好的,不能让我们看到,避免我们的一些“特殊”操作,使其不能正常工作.编程源于生活.在python中也有对对象的封装操作,使

  • Python面向对象之类的封装操作示例

    本文实例讲述了Python面向对象之类的封装操作.分享给大家供大家参考,具体如下: 承接上一节<Python面向对象之类和实例>,学了Student类的定义及实例化,每个实例都拥有各自的name和score.现在若需要打印一个学生的成绩,可定义函数 print_score() 该函数为类外的函数,如下: class Student(object): def __init__(self, name, score): self.name = name self.score = score May

  • 详析Python面向对象中的继承

    目录 一单继承 1.继承的基本语法格式如下 2.查看类继承情况 3.继承中的属性和方法 4.初始化函数__init__()和super 二多层继承 三多重继承 一 单继承 类继承作为python的三大特性之一,在我们学习python的时候是必不可少的.使用类继承,能够大大减少重复代码的编写.现来记录下,python中关于类继承的一些知识点.类的继承有单继承,多层继承以及多重继承,先来看看单继承. 1. 继承的基本语法格式如下 #类继承语法格式,B类继承A类 class A():     类属性

  • JavaScript面向对象中的封装和继承你了解吗

    目录 1.面向对象 1.封装 2.原型对象 3.继承 总结 1.面向对象 [三大显著特征]: 封装.继承.多态 1.封装 [解释]: 封装的本质就是将有关联的代码组合在一起. [优势]: 保证代码可以复用提高代码的维护效率 [以前的封装方法]: 函数封装 function fn(){} 命名空间封装 let o={ name:'zhangsan', age:20 } let obj={ name:'lisi', age:18 } [新的封装方法]: 构造函数 //自定义构造函数 function

  • Python面向对象编程基础解析(二)

    Python最近挺火呀,比鹿晗薛之谦还要火,当然是在程序员之间.下面我们看看有关Python的相关内容. 上一篇文章我们已经介绍了部分Python面向对象编程基础的知识,大家可以参阅:Python面向对象编程基础解析(一),接下来,我们看看另一篇. 封装 1.为什么要封装? 封装就是要把数据属性和方法的具体实现细节隐藏起来,只提供一个接口.封装可以不用关心对象是如何构建的,其实在面向对象中,封装其实是最考验水平的 2.封装包括数据的封装和函数的封装,数据的封装是为了保护隐私,函数的封装是为了隔离

  • Python面向对象编程之类的概念

    目录 1.面向对象基本概念 1.1 万物皆对象 1.2 面向对象编程 1.3 面向对象的特征 2.Python面向对象的术语 3.Python类的构建 3.1 类的基本构建 3.2 类的构造函数 3.3 类的属性 3.4 类的方法 1.面向对象基本概念 1.1 万物皆对象 Python语言的中所有数据类型都是对象.函数是对象.模块是对象 Python所有类都是继承最基础的类object Python语言中的数据类型的操作功能都是类方法的体现 1.2 面向对象编程 面向对象编程又叫OOP(Obje

  • Python 面向对象之封装、继承、多态操作实例分析

    本文实例讲述了Python 面向对象之封装.继承.多态操作.分享给大家供大家参考,具体如下: 封装.继承.多态 是面向对象的3大特性 为啥要封装 好处 在使用面向过程编程时,当需要对数据处理时,需要考虑用哪个模板中哪个函数来进行操作,但是当用面向对象编程时,因为已经将数据存储到了这个独立的空间中,这个独立的空间(即对象)中通过一个特殊的变量(class)能够获取到类(模板),而且这个类中的方法是有一定数量的,与此类无关的将不会出现在本类中,因此需要对数据处理时,可以很快速的定位到需要的方法是谁

  • Python面向对象程序设计类的封装与继承用法示例

    本文实例讲述了Python面向对象程序设计类的封装与继承用法.分享给大家供大家参考,具体如下: 访问限制(封装) 1.概念 面向对象语言的三大特征:封装, 继承, 多态. 广义的封装: 类和函数的定义本身就是封装的体现. 狭义的封装:一个类的某些属性,不希望外界直接访问,而是把这个属性私有化[只有当前类持有],然后暴露给外界一个访问的方法. 封装的本质:就是属性私有化的过程. 封装的好处:提供了数据的复用性,保证了数据的安全性. 举例:插排 2.使用 class Person(object):

  • Python面向对象程序设计中类的定义、实例化、封装及私有变量/方法详解

    本文实例讲述了Python面向对象程序设计中类的定义.实例化.封装及私有变量/方法.分享给大家供大家参考,具体如下: 1. 定义类 python中定义一个类的格式如下: class MyClass(object): def __init__(self,data1,data2): self.__data1=data1 self.data2=data2 def __func1(self): print("MyClass类的私有方法被调用!") def print_data(self): s

随机推荐