1、私有成员变量介绍

(1)私有成员变量概念

在Python面向对象中,把类的某些属性,如果在使用的过程中,不希望被外界直接访问,就可以将该属性设置为私有的,即只有当前类持有,然后暴露给外界一个访问的函数,来实现间接的访问对象属性,这就是类中数据的封装。

如果类中的属性不想被外界直接访问,则可以在属性的前面添加两个下划线__,此时称该属性为私有属性,即私有成员变量。

封装的本质:就是属性的私有化。

(2)私有成员变量特点

只能在类的内部被直接访问,在外界不能直接访问。

(3)私有成员变量体验

1)属性不被私有化情况:

# 1.属性不私有化的时候
class Student():
def __init__(self, name, age):
self.name = name
self.age = age def tellMe(self):
print(f"大家好,我是{self.name},年龄{self.age}") # 创建对象
stu = Student("孙悟空", 18) # 通过对象.成员函数,调用函数并访问对象中的成员变量
stu.tellMe() # 通过对象.属性,直接访问对象中的属性
print(f"大家好,我是{stu.name},年龄{stu.age}") # 通过对象直接访问对象的属性,并给属性赋值
stu.name = "齐天大圣"
print(stu.name) # 齐天大圣 """
输出结果:
大家好,我是孙悟空,年龄18
大家好,我是孙悟空,年龄18
齐天大圣 可以看到都可以访问到。
"""

2)属性被私有化情况:

# 2.属性私有化的时候
class Student():
def __init__(self, name, age):
self.name = name
# 私有化age属性
self.__age = age def tellMe(self):
print(f"大家好,我是{self.name},年龄{self.__age}") # 创建对象
stu = Student("孙悟空", 18) # 通过对象.成员函数,调用函数并访问对象中的成员变量
# 可以访问当对象中的私有成员变量
# 输出:大家好,我是孙悟空,年龄18
stu.tellMe() # 通过对象.属性,直接访问对象中的属性
# 报错:
# AttributeError: 'Student' object has no attribute '__age'
# print(f"大家好,我是{stu.name},年龄{stu.__age}") # 直接通过对象.属性,修改成员变量属性值
# 可以
stu.name = "齐天大圣"
print(stu.name) # 齐天大圣
# 结果:大家好,我是齐天大圣,年龄18
stu.tellMe() # 直接通过对象.属性,修改私有成员变量属性值
# 输出了结果
stu.__age = 30
print(stu.__age) # 30
# 结果:大家好,我是齐天大圣,年龄18
# 但是通过调用对象中的方法,查看对象的私有属性
# 结果并没有变化,还是18
stu.tellMe() """
但是我们通过__dict__属性查看stu对象的所有成员:
{'name': '齐天大圣', '_Student__age': 18, '__age': 30}
可以看到我们并没有修改原有的属性'_Student__age': 18,
而是给stu对象新添加了一个属性 '__age': 30。
所以说我们并没有对私有成员变量age重新赋值成功。
只有 '_Student__age': 18为什么指的是私有变量的age,
我们下面的私有成员原理就会讲解。
"""
print(stu.__dict__)

说明:双下划线开头的属性,是对象的隐藏属性,隐藏属性只能在类的内部访问,无法通过对象访问

2、属性私有化工作原理

class Student():
def __init__(self, name, age):
self.name = name
# 私有化成员属性
self.__age = age def tellMe(self):
print(f"大家好,我是{self.name},年龄{self.__age}") """
其实隐藏(私有化)属性只不过是Python自动为属性改了一个名字
实际上是将名字修改为了,_类名__属性名
比如 __age -> _Student__name,
也就是在原有的变量名前边加上了 _类名。
""" # 创建对象
stu = Student("孙悟空", 18)
# 结果:大家好,我是孙悟空,年龄18
stu.tellMe() # 直接通过对象.属性,修改对象的私有成员变量
# 通过下面的打印结果可以看到,修改成功了
stu._Student__age = 30
# 结果:大家好,我是孙悟空,年龄30
stu.tellMe()

总结:

Python中,并没有 真正意义私有,实际是对成员变量的名称做了一些特殊处理,使得外界无法访问到。

所以定义为双下划线__开头的属性,实际上依然可以在外部访问。

但平时我们不建议这么访问私有属性。

3、定义成员变量的标识符规范

  • xxx:普通变量。
  • _xxx:使用_开头的属性为受保护的变量,没有特殊需要不要修改。
  • __xxx:使用双_开头的属性私有变量,在外界不能直接被访问。
  • __xxx__:系统的内置变量。
  • xx_:单后置下划线,用于避免与Python关键词的冲突。

示例:

class Student():
def __init__(self, name, age, gender):
# 在变量的前面添加一个下划线,属于特殊变量,则认为该变量受保护的
self._name = name # 在变量的前添加双下划线。表示定义私有变量。
# 特点:对象不能直接使用
self.__age = age # 在变量的前后各添加两个下划线,属于特殊变量,一般认为这种变量都是系统的内置变量或者内置函数
# 特点:在类的外面也可以直接访问,但不建议使用
self.__gender__ = gender stu = Student("唐僧", 66, "男")
print(stu._name) # 唐僧
print(stu.__gender__) # 男

4、私有成员变量的获取和设置方式

(1)方式:

如何获取(修改)对象中的私有属性?

需要提供一个getter()setter()方法使外部可以访问到属性。

  • getter()方法用来获取对象中的指定属性。

    getter()方法的规范命名为get_属性名

  • setter()方法用来设置对象中的指定属性。

    setter()方法的规范命名为set_属性名

(2)格式:

getter()方法:会有一个返回值。

    def get_xxx(self):
return self.属性名

setter()方法:没有返回值,但是方法多一个参数。

def set_xxx(self, 形参名称):
self.属性名 = 形参名称的值

(3)示例:

class Student():
def __init__(self, name, age):
# 普通变量
self.name = name
# 私有变量
self.__age = age def tellMe(self):
print(f"大家好,我是{self.name},年龄{self.__age}") def get_name(self):
"""
get_name()用来获取对象的name属性
"""
return self.name def set_name(self, name):
"""
set_name()用来设置对象的name属性
"""
self.name = name def get_age(self):
return self.__age def set_age(self, age):
if age > 0:
self.__age = age # 创建对象
stu = Student("孙悟空", 18)
# 输出结果:大家好,我是孙悟空,年龄18
stu.tellMe() # 修改属性值
stu.set_name("齐天大圣")
stu.set_age(30) # 打印属性值
# 结果都是:大家好,我是齐天大圣,年龄30
stu.tellMe()
print(f"大家好,我是{stu.get_name()},年龄{stu.get_age()}") """
私有属性只能在类内部使用,对象不能直接使用,但是我们可以通过在类内部定义公有方法对私有属性进行调用或修改,然后对象在调用这个公有方法使用
"""

(4)总结:

  • 不管是普通方法和私有方法都可以使用getter()方法和setter()方法来获取或设置属性值,我们日常开发中也经常是这么编程的。
  • 使用封装,确实增加了类的定义的复杂程度,但是它也确保了数据的安全性。
  • 增加了getter()方法和setter()方法,很好的控制的属性是否是只读的,

    如果希望属性是只读的,则可以直接去掉setter()方法,

    如果希望属性不能被外部访问,则可以直接去掉getter()方法。
  • 使用setter()方法设置属性,可以增加数据的验证,确保数据的值是正确的,如:
        def set_age(self, age):
    if age > 0:
    self.__age = age
  • 同理使用getter()方法获取属性时,或者使用setter()方法设置属性时,可以在读取属性和修改属性的同时,对数据做一些其他的处理。

『无为则无心』Python面向对象 — 51、私有成员变量(类中数据的封装)的更多相关文章

  1. 『无为则无心』Python面向对象 — 55、多层继承和继承中的私有成员

    目录 1.Python支持多层继承 (1)多层继承实现 (2)多层继承和多重继承区别 2.继承中的私有成员 (1)继承中父类私有属性和私有方法 (2)获取和修改私有属性值 1.Python支持多层继承 ...

  2. 『无为则无心』Python面向对象 — 45、面向对象编程

    目录 1.面向对象编程的概念 2.面向对象编程和面向过程编程的区别 (1)面向过程编程 (2)面向对象编程 3.举例理解面向对象 4.Python的面向对象编程 5.面向对象的几大核心特性 1.面向对 ...

  3. 『无为则无心』Python面向对象 — 46、类和对象

    目录 1.理解类和对象 2.类 3.对象 4.Python中的对象 5.类和对象的定义 (1)定义类 (2)创建对象 (3)练习 6.拓展:isinstance() 函数 1.理解类和对象 (1)类和 ...

  4. 『无为则无心』Python面向对象 — 52、私有成员方法(类中行为的封装)

    Python对于类的成员没有严格的访问控制限制,这与其他面向对象的编程语言是有所区别的. 关于私有方法其实和私有属性差不多,有如下要点: 1.通常我们约定,两个下划线开头的方法是私有方法. 2.类内部 ...

  5. 『无为则无心』Python面向对象 — 53、对Python中封装的介绍

    目录 1.继承的概念 2.继承的好处 3.继承体验 4.单继承 5.多继承 1.继承的概念 在Python中,如果两个类存在父子级别的继承关系,子类中即便没有任何属性和方法,此时创建一个子类对象,那么 ...

  6. 『无为则无心』Python面向对象 — 47、Python中的self详解

    目录 1.self的作用 2.self的使用注意事项 (1)self代表类的实例,而非类 (2)self不必非写成self,只是一种规范. (3)类中方法的形参中一定要写self,包括内置函数 (4) ...

  7. 『无为则无心』Python面向对象 — 54、重写和super()函数

    目录 1.重写 2.super()函数 方式一 方式二 __mro__内置类属性说明 1.重写 在子类中如果有和父类同名的方法,则通过子类实例去调用该方法时,会调用子类中的该方法而不是父类的方法,这个 ...

  8. 『无为则无心』Python面向对象 — 58、类方法和静态方法

    目录 1.实例方法 2.类方法 (1)类方法特点 (2)类方法使用场景 3.静态方法 (1)静态方法特点 (2)静态方法使用场景 1.实例方法 实例方法既可以调用静态方法也可以调用类方法. # 定义一 ...

  9. 『无为则无心』Python面向对象 — 59、魔法方法

    目录 1.魔法方法__new__() 2.魔法方法__init__() 3.魔法方法__del__() 4.魔法方法__str__()和__repr__() 5.魔法方法__call__() 6.魔法 ...

随机推荐

  1. 在 k8s 中的 jenkins 集成 sonarqube 实现代码质量检查

    不乱于心,不困于情,不畏将来,不念过往,如此安好 --<不宠无惊过一生>丰子恺 概述 关于在 k8s 中安装 jenkins 和 sornarqube 可以查看下面的文章: 在 k8s 中 ...

  2. 《剑指offer》面试题20. 表示数值的字符串

    问题描述 请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100"."5e2"."-123"."3.1 ...

  3. SQLServer触发器调用JavaWeb接口

    这几天接到一个需求需要吧不同系统的数据库进行同步,需要我做一个中间平台进行连接,瞬间就想到了触发器调用接口然后通过API进行传递再写入另一个数据库. sqlServer触发器调用JavaWeb接口 1 ...

  4. 【刷题-LeetCode】122 Best Time to Buy and Sell Stock II

    Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price of a ...

  5. 宣布与Epic Games合作,为虚幻引擎创造Cesium

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 没有什么能比支持史诗游戏和史诗巨无霸计划(Epic MegaGr ...

  6. golang中内存地址计算-根据内存地址获取下一个内存地址对应的值

    package main import ( "fmt" "unsafe" ) func main() { // 根据内存地址获取下一个字节内存地址对应的值 da ...

  7. Typecho博客支持emoji表情设置

    介绍 大家在typecho博客写文章时,很多人都喜欢使用emoji表情(比如这些图标)但是typecho的数据库类型默认不支持emoji编码,因为Emoji是一种在Unicode位于u1F601-u1 ...

  8. 【简记】SpringBoot禁用Swagger

    楔子 Swagger 是 Java Web 开发中常用的接口文档生成类库,在开发和前后端联调时使用它来模拟接口调用能提高开发效率.但是,在生产环境可能并不需要它,一个原因是启用它会延长程序启动时间(动 ...

  9. python3 爬取深圳主板公司名称,公司网址

    需要阅读的文档: Requests:http://cn.python-requests.org/zh_CN/latest/user/quickstart.html BeautifulSoup:http ...

  10. 介绍一个golang库:fastcache

    学习VictoriaMetrics源码的时候发现,VictoriaMetrics的缓存部分,使用了同一产品下的fastcache.下面分享阅读fastcache源码的的结论: 1.官方介绍 fastc ...