Python面向对象特性 - 封装

类中的私有属性

私有属性包括私有变量和私有方法,在 Python 中,在变量名或者方法名前面加上双下划线,这个属性就成为了类的私有属性。
?

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def __fun(self):
        print(self.__class__)

    def say(self):
            self.__fun()       # 自动转换为 调用 _Person__fun 方法
        print(self.__name + ‘ ‘ + str(self.__age))   # 自动转换为 调用 \_Person\_\_name 和 \_Person\_\_age 属性~

p = Person(‘Kitty‘, 18)
p.say()

# 输出结果:
Kitty 18

上述示例中,__name 和 __age 为类的私有变量,私有变量仅能在类中进行访问,在类的外部访问不到。

p = Person(‘Kitty‘, 18)
print(p.__name)

# 报错信息:
AttributeError: ‘Person‘ object has no attribute ‘__name‘

?
其实在类中定义私有属性时,__name 和 __age 已经自动变形为 _Person__name 和 _Person__age,__fun 自动变形为 _Person__fun,即私有属性会自动变形为_类名__属性~

p = Person(‘Kitty‘, 18)
print(p.__dict__)

# 输出结果:
{‘_Person__name‘: ‘Kitty‘, ‘_Person__age‘: 18}

?
当在类的内部通过属性名称访问私有属性时,会自动进行转换,例如 self.__name 转换为 self._Person__name,在类的外部不会进行这样的自动转换~
?
类的私有属性只是在语法上做了访问限制,但是并没有真正限制从外部的访问。在外部不能通过 对象.__属性 来进行访问,但是可以通过变形后的属性名来进行访问~

p = Person(‘Kitty‘, 18)
# print(p.__name)      # 不能这样访问
print(p._Person__name)
p._Person__fun()

# 结果输出:
Kitty
<class ‘__main__.Person‘>

对私有属性的访问限制只是一种规范,在开发过程中一般不允许在外部通过这种方式访问私有属性~
?
私有属性的变形只在类的内部生效,在定义后的赋值操作,不会变形~

p = Person(‘Kitty‘, 18)
p.__name = ‘abc‘
print(p.__dict__)
print(p.__name)     # 调用的是 __name 属性,不是私有属性

# 输出结果:
{‘_Person__name‘: ‘Kitty‘, ‘_Person__age‘: 18, ‘__name‘: ‘abc‘}   # 这个属性就叫 __name
abc

?
在子类中定义的私有属性若是和父类中的私有属性同名,不会覆盖父类的这些私有属性,因为这些私有属性变形后的名称不同,子类:_子类名__属性,父类:_父类名__属性~

class Fu:
    __key = 123    # 静态私有属性

    def __init__(self, name):
        self.__name = name

class Zi(Fu):
    def get_name(self):
        print(self.__name)    # 变形为 self._Zi__name

    def get_key(self):
        print(Fu.__key)     # 变形为 self._Zi__key

zi = Zi(‘hello‘)
zi.get_name()     # 报错信息:AttributeError: ‘Zi‘ object has no attribute ‘_Zi__name‘
zi.get_key()     # 报错信息:AttributeError: type object ‘Fu‘ has no attribute ‘_Zi__key‘

?
若是父类中定义的方法不想被子类调用到,可以将方法定义为私有方法~

class A:
    def __fun(self): # 在定义时就变形为_A__fun
        print(‘from A‘)
    def test(self):
        self.__fun() # 变形为 self._A__fun(),即以当前的类为准

class B(A):
    def __fun(self):
        print(‘from B‘)

b=B()
b.test()    # 调用 A类中的test方法,test方法中的 self.__fun() 调用的是 A类中的私有方法__fun()

# 输出结果:
from A

封装的优势在于将类内部的实现细节隐藏起来,调用者无需了解,直接调用对应的方法即可(方法名,参数都不改变),若功能需要改变,只需要在类的内部进行调整,外部的调用代码无需改变~

property属性

property为内置装饰器函数,只在面向对象中使用。@property装饰器 可以将 对方法的调用转为 对变量的调用。示例如下:

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def name(self):
        return self.__name

    @property
    def age(self):
        return self.__age

p = Person(‘Kitty‘, 18)
print(p.name)
print(p.age)

# 结果输出:
Kitty
18

p.name 和 p.age 其实是执行了一个函数,然后将结果返回。这种特性的使用方式遵循了统一访问的原则。
 
p.属性 的这个过程也可以做一些运算操作然后将结果返回~

class Room:
    def __init__(self, width, length, high):
        self.__width = width
        self.__length = length
        self.__high = high
    def area(self):
        return self.__width * self.__length * self.__high

room = Room(1, 2, 3)
print(room.area())      # 6

除了 @property,还有 @属性.setter@属性.deleter,要注意的是,定义了 property 后才能定义 属性.setter,属性.deleter ~

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, value):
        if not isinstance(value, str):  # 在设定值之前进行类型检查
            raise TypeError(‘%s must be str‘ %value)
        self.__name = value

    @name.deleter
    def name(self):
        raise TypeError(‘Can not delete‘)

    @property
    def age(self):
        return self.__age

p = Person(‘Kitty‘, 18)
p.name = ‘nihao‘
print(p.name)
del p.name   # TypeError: Can not delete

说明:
执行 p.name 的时候,调用 @name.setter 修饰的方法,这样的赋值方式在真正的赋值之前可以做一些类型检验的操作,或者别的自定义操作,更具灵活性~
执行 del p.name 的时候,调用 @name.deleter 修饰的方法
 
在使用 @property,@属性.setter 和 @属性.deleter 的时候,这几个地方必须保持一致,即属性名称需要保持一致。

上述示例也可以通过如下方式实现:

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def get_name(self):
        return self.__name

    def set_name(self, value):
        if not isinstance(value, str):  # 在设定值之前进行类型检查
            raise TypeError(‘%s must be str‘ %value)
        self.__name = value

    def del_name(self):
        print(‘delete name‘)

    name = property(get_name, set_name, del_name)

    @property
    def age(self):
        return self.__age

Tip:

  • 使用 property 修饰的方法,除了 self 不能有别的参数,@属性.deleter也一样;
  • 使用 @属性.setter 修饰的方法除了self 以外只能有一个参数~

.................^_^

原文地址:http://blog.51cto.com/ljbaby/2348633

时间: 2024-10-07 09:54:52

Python面向对象特性 - 封装的相关文章

Python面向对象编程-封装

1引言 你点击了桌面上的Chrome图标,一个浏览器窗口出现了,输入网址就可以在Internet世界愉快玩耍.这一切是怎么实现的呢?Chromium这个多进程的程序是如何启动各个进程的呢?浏览器主进程(界面进程)启动了哪些线程?如何启动的呢?这些问题一直萦绕在心头,一起来看看源代码吧.本文主要针对Chromium for Mac的源代码,其它操作系统大同小异. 2背景知识 浏览器作为一个应用程序,是以进程的形式运行在操作系统上的.首先,Chromium是一个多进程的应用程序,我们需要了解Chro

oldboy 21th day. I love Python. 面向对象之封装, 多态, 继承 三大特性

一, 主要内容: 接口类:( 只是在工作中, 书写的一种规范.) 抽象类: 用处: 在工作中, 如果你要是规定几个类, 必须有一样的方法, 你要是抽象类. 封装: 1, 将一些属性或者方法 (一些有用的信息) 放置在一个空间中. 2, 私有成员的封装:私有静态变量, 私有属性, 私有方法 特点: 在变量前+__双下划线, 并且在类外面,子类访问私有变量,私有方法 是访问不到的. 因为私有成员,在运行时, 都会变成: _类名__变量名 所以你在类的外部,或者派生类中都不可访问. 有些方法, 变量,

Python面向对象特性 - 继承

面向对象有3大特性:继承.多态.封装,本章介绍 Python中的 继承 特性~? 什么是继承 继承是创建类的一种方式,在 Python中支持多继承,即在创建类的时候可以继承一个或者多个父类.在继承关系中,被继承的类通常称为父类(或超类,基类),新建的类则称为子类(或派生类).?继承的优势在于可以有效地重用代码,提高代码的可读性~?继承示例: class Fu_1: # 父类 pass class Fu_2: # 父类 pass class Zi_1(Fu_1): # 单继承 pass class

python面向对象之 封装(Day25)

封装: 隐藏对象的属性和实现细节,仅对外提供公共访问方式 好处:1.将变化隔离 2.便于使用 3.提高复用性 4.提高安全性 封装原则: 1.将不需要对外提供的内容隐藏起来 2.把属性都隐藏,提供公共方法对其访问 二.私有变量和私有方法 在Python中用双下划线开头的方式将属性隐藏起来(设置成私有的) 2.1 私有变量 #其实这仅仅这是一种变形操作 #类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式: class A: __N=0 #类的数据属性就应该是共享的,但是语法上是

python面向对象编程 -- 封装、继承(python3.5)

面向对象编程三要素:封装.继承和多态.本文主要看和封装.继承相关的概念:在python中多态的概念比较模糊,本文不做讨论. 1 封装 封装:将数据和操作组装到一起,对外只暴露一些接口供类外部或子类访问,隐藏数据和操作的实现细节. 在其他面向对象语言,比如java中,属性访问控制一般有三种状态:private.protectd.public.python中没有什么东西是完全不可见的,没有任何机制可以强制性的隐藏数据.所以在python中不存在真正的只能在对象内部访问的属性.一个被大多数的pytho

python—面向对象的封装

封装 私有属性 class Teacher: __identifier = 'Teacher' #私有静态属性 def __init__(self,name,pwd) self.name = name self.__pwd = pwd #私有属性 内部使用,外部不能使用 def pwd(self): print(self.__pwd) alex = Teacher('alex','3714') alex.pwd() class Teacher: __identifier = 'Teacher'

Python 面向对象特性二 多态(3-7)

接口类: 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能 在Python中是没有接口的概念的(接口是在Java里的) from abc import ABCMeta,abstractmethod#调用abc模块中的抽象方法 # 接口类 : 接口类就是一个规范 接口类一般是项目设计人员写好的 class Pa

Python面向对象特性 - 多态

Python中的多态 多态 多态指的是一类事物有多种形态.多态的实现需要依赖于继承~ import abc class File(metaclass=abc.ABCMeta): @abc.abstractmethod def read(self): pass @abc.abstractmethod def write(self): pass class Txt(File): # 文本数据的读写 def read(self): print('读取文本数据') def write(self): pr

Python面向对象之封装

类class继承(单继承.多继承) 类方法@classmethod修饰实例方法def fn(self)静态方法@staticmethod修饰 代码区: class people: # 定义基本属性 name=''; age=0; # 定义私有属性,类的外部无法访问 __weight=0; def __init__(self, n, a, w): self.name = n; self.age=a; self.weight=w; def speak(self): print('%s is %s y