第六章 Python面向对象 02-封装

封装

我们在类中可以定义一些属性、方法,对于有些属性来说,我们可能不希望暴露给外界,因为在外界直接访问的时候(主要是直接修改的时候)可能设置的值并不是我们想要的一些值,可能会对我们的逻辑产生影响。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
# 创建Person对象
x = Person('xiaobai', 19)
# 类外直接访问属性,修改
x.age = 2000

在上述代码中可以看到,在类外访问x对象的age属性,并且将值修改为2000。这个操作并没有什么语法错误,可以成功的将age属性设置为2000。从语法的角度出发没有错,可是从我们的逻辑出发却是有问题的,因为我希望一个人类的年龄应该限制在[0, 150]的范围之内的!此时,我就非常不希望外面直接修改age属性的值

如何解决上述的问题呢?

1. 可见性

在类中定义的属性、方法都是有一定的可见性的,也就是在哪里可以看到、可以访问。在Python中,可见性分为三种: 公共的、保护的、私有的。

可见性可见性描述可见性修饰
公共的在任何的位置都可以访问,默认默认创建的属性、方法都是公共的可见性,不需要什么操作
保护的只能够在当前的模块中访问使用一个下划线开头,例如: _age
私有的只能够在当前的类中访问使用两个下划线开头,例如: __age
class Person:
    # 为了不让外界直接访问到age属性,这里将名字设置为了 __age
    def __init__(self, name, age):
        self.name = name
        self.__age = age
        
x = Person('xiaobai', 18)
# print(x.__age)	这里会报错,因为找不到这个属性

这样一来,我们就可以将属性私有化起来,不让外界直接访问了!

拓展知识点:

​ Python中所谓的“私有化”,其实是“防君子,不防小人”。Python的研发人员遵循的原则是“大家都是成年人,知道事情的轻重,知道有些事情可以做,有些事情不能做”。**Python中并没有真正的私有化,之所以访问不到了,是因为在存储的时候修改了名字!**这些被私有化的成员的名字被定义为 _类名__特征名

# 在上述的代码中,直接访问__age是访问不到的
# 因为Python在存储这个属性的时候,并不是按照__age来存储的,而是按照 _Person__age 来存储的
# 使用下面的访问,访问属性,看看是不是成功的访问到了!
print(x._Person__age)

2. 方法属性化

我们已经成功的将某些属性隐藏起来了,外界不能直接访问到了。可是别忘了我们的初衷。我们为什么要隐藏起来这个属性的?其实就是因为外界直接去修改的时候,可能会设置一些“逻辑错误”的值,给我们带来麻烦。但是私有化起来之后,外界就彻底无法访问了,这样也是不妥的。因此我们就需要提供这些私有属性的对应的访问的方法,并且在这些方法中,添加我们自己的过滤的条件。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.set_age(age)
        
    # 提供set方法,可以让外界通过调用这个方法,来修改属性__age的值
    # 在这个方法中,可以添加上自己的业务逻辑,实现对外界修改值的过滤
    def set_age(self, age):
        if 0 <= age <= 150:
            self.__age = age
    
    # 提供get方法,可以让外界通过调用这个方法,来获取属性__age的值
    def get_age(self):
        return self.__age
    
# 创建对象
x = Person('xiaobai', 18)

# 通过方法访问属性
x.set_age(2000)
print(x.get_age())

通过上述的方式,的确可以实现属性的私有化,并且也可以在类外通过特定的方式访问到属性。但是使用起来其实是不方便的。出于方便性的考虑,我们可以将set/get方法属性化,使得在类外使用的时候,有着跟访问属性一样的便利性,同时还能在类内保持自己的业务逻辑处理。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    # get方法属性化,添加@property
    @property
    def age(self):
        return self.__age
    
    # set方法属性化,添加@属性.setter
    # 这里需要提前给属性添加@property属性,单独写这个是会出错的
    @age.setter
    def age(self, age):
        if 0 <= age <= 150:
            self.__age = age

            
#
p = Person('xiaobai', 19)
# 访问“属性”
p.age = 19
print(p.age)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值