本文主要介绍python中面向对象封装的细节。在Python中,也有对对象的封装操作,对外界只提供固定的访问方式,不能访问其内部私有属性和方法。具体如下,可以参考需要的小伙伴。
目录
一个封装的概念II _属性和方法的私有化_ _ 1。单下划线_2。双下划线__3。访问子类III中父类的私有属性和方法。访问和修改类1的私有属性和方法。自定义公共方法2。财产
一 封装的概念
其实包装在我们的生活中无处不在,比如电视机、电脑、手机等物品。通常我们只能看到它的外在造型,使用它们提供的功能,却看不到它内部复杂的硬件构成。这些都是打包好的,不能被我们看到,以免我们的一些“特殊”操作使其无法正常工作。编程来源于生活。在python中,也有对对象的封装操作,使其只对外界提供固定的访问方式,而不能访问其内部私有属性和方法。python中的封装一般是指类属性和方法的封装,即类属性的私有化和类方法的私有化,下面的总结中会详细介绍。
二 _ 和__ 对属性和方法的私有化
1. 单下划线_
当类中的属性和方法以_单下划线开头时,意味着它们是该类的受保护变量和方法。根据编码约定,它们不希望被外部访问。但是如果要访问,就不会报错。
如下:
A类():
# _声明是保护属性和保护方法。
_name='张三'
def __init__(self):
自我。_年龄=23岁
def _method(自身):
打印('我叫{},今年{}岁'。格式(自我。_name,self。_年龄))
if __name__=='__main__ ':
a=A()
#打印a类目录
打印(a. __目录_ _())
#访问保护变量和保护方法
打印(姓名)
a._方法()
输出结果:
['_age ',' __module__ ',' _name ',' __init__ ',' _ _ method ',' __dict__ ',' __weakref__ ',' __doc__ ',' __repr__ ',' __hash__ ',' __str__ ',' __getattribute__ ',' __setattr__ ',' __delattr__ ',' __lt__ ',' __le__ ',' __eq__ ',','
张三
我叫张三,今年23岁。
可以看出,以_单下划线开头的属性和方法实际上是可以在类外访问的,但是按照约定,当我们看到这样的属性和方法时,不应该在类外访问。
2. 双下划线__
尽管以单下划线开头的上述属性和方法受到保护,但仍然可以从外部访问它们。当你看到以双下划线_ _开头的属性和方法时,请记住它们是类的私有属性和私有方法。在类之外和子类中访问类的属性和方法的方法不能被访问或修改,如下所示
B类():
# _ _宣布私有化
__name='张三'
def __init__(self):
自我。_ _年龄=23岁
自我。__luange='python '
def __method(自我):
#私有方法
Print('我叫{},今年{}岁,我喜欢{}。'。格式(自我。__name,self。_ _年龄,自我。_ _栾格))
定义乐趣(自我):
#公共方法
打印(“这是一个公共方法”)
if __name__=='__main__ ':
b=B()
#打印b类目录
print(b.__dir__())
#访问b类的私有属性和私有方法。
b .乐趣()
打印(b . _ _姓名,b . _ _年龄,b . _ _栾)
b._ _方法()
输出结果:
['_B__age ',' _B__luange ',' __module__ ',' _B__name ',' __init__ ',' _B__method ',' __dict__ ',' __weakref__ ',' __doc__ ',' __repr__ ',' __hash__ ',' __str__ ',' __getattribute__ ',' __setattr__ ',' __delattr__ ',' __lt__ '
这是一个公共方法
回溯(最近一次呼叫):
文件“c:/users/admin/python-learning/python learning files/python basics/python class encapsulation . py”,第56行,在模块中
打印(b . _ _姓名,b . _ _年龄,b . _ _栾)
attribute错误:“B”对象没有属性“__name”
从结果中可以看出,B类的公共方法fun()是正常输出的,但是当我们访问私有属性name时,抛出一个错误:B类没有name属性。当上面有下划线时,我们打印A类的dir,可以看到在dir中A类的name属性和方法如下
上面我们也打印了类B的私有属性和私有方法,如下:
可以看出,私有属性和私有方法都是以_B__ attributes和_B__ methods的形式出现,所以我们以__ name或name的形式访问它们是错误的。事实上,如果我们以类名()的形式访问它们。_ class name _ _ attribute(实例属性)或类名。_ class name _ _ attribute(类属性),我们还是会成功的。如下
B类():
# _ _宣布私有化
__name='张三'
def __init__(self):
自我。_ _年龄=23岁
自我。__luange='python '
def __method(自我):
#私有方法
Print('我叫{},今年{}岁,我喜欢{}。'。格式(自我。__name,self。_ _年龄,自我。_ _栾格))
定义乐趣(自我):
#公共方法
打印(“这是一个公共方法”)
if __name__=='__main__ ':
b=B()
#打印b类目录
print(b.__dir__())
#访问b类的私有属性和私有方法。
b .乐趣()
打印(姓名,年龄,性别)
b._ B _ _方法()
结果如下:
['_B__age ',' _B__luange ',' __module__ ',' _B__name ',' __init__ ',' _B__method ',' __dict__ ',' __weakref__ ',' __doc__ ',' __repr__ ',' __hash__ ',' __str__ ',' __getattribute__ ',' __setattr__ ',' __delattr__ ',' __lt__ '
这是一个公共方法
张三23蟒
我的名字叫张三。我今年23岁。我喜欢python。
3. 子类中访问父类的私有属性和私有方法
子类无法访问父类的私有属性和私有方法:
B类():
# _ _宣布私有化
__name='张三'
def __init__(self):
自我。_ _年龄=23岁
自我。__luange='python '
def __method(自我):
#私有方法
Print('我叫{},今年{}岁,我喜欢{}。'。格式(自我。__name,self。_ _年龄,自我。_ _栾格))
定义乐趣(自我):
#公共方法
打印(“这是一个公共方法”)
丙类(乙类):
def __init__(self):
超级()。__init__()
def fun1(自身):
#访问父类b的私有属性和私有方法。
打印(自我。__name,self。_ _年龄,自我。_ _栾格)
自我。_ _方法()
if __name__=='__main__ ':
c=C()
c.fun1()
输出结果:
attribute错误:“C”对象没有属性“_C__name”
attribute错误:“C”对象没有属性“_C__method”
可见子类是无法访问父类的私有属性和私有方法的。
当子类中的属性和方法与父类的私有属性和方法同名时,父类的私有属性和方法不会被覆盖。
B类():
# _ _宣布私有化
__name='张三'
def __init__(self):
自我。_ _年龄=23岁
自我。__luange='python '
def __method(自我):
#私有方法
Print('我叫{},今年{}岁,我喜欢{}。'。格式(自我。__name,self。_ _年龄,自我。_ _栾格))
定义乐趣(自我):
#公共方法
打印(“这是一个公共方法”)
丙类(乙类):
__name='李四'
def __init__(self):
超级()。__init__()
自我。_ _年龄=24岁
自我。__luange='C '
def fun1(自身):
#访问父类b的私有属性和私有方法。
打印(自我。__name,self。_ _年龄,自我。_ _栾格)
自我。_ _方法()
def __method(自我):
# C类的私有方法,与父方法同名,但不重写父方法
Print('我叫{},今年{}岁,我喜欢{}。'。格式(自我。__name,self。_ _年龄,自我。_ _栾格))
#调用父类的私有方法
b()。_ B _ _方法()
if __name__=='__main__ ':
c=C()
#访问c类的私有方法。
c._ C _ _方法()
结果如下:
我叫李四,今年24岁,喜欢c。
我的名字叫张三。我今年23岁。我喜欢python。
可以看到,子类C并没有覆盖父类b的__method()方法,这是为什么呢?让我们打印B和C的目录,如下:
['_B__age ',' _B__luange ',' _C__age ',' _C__luange ',' fun1 ',
' C _ method ',' _doc__ ',' _ B _ name ',' _ B _ method ',' _ C _ name ',]
可以看到,在C类的dir中,父类B的私有属性和方法以_B__ attributes (methods)的形式存在,而II类C的私有属性和方法以_C__ attributes (methods)的形式存在,即类的私有属性和方法会以_ class name _ attributes (methods)的形式存在于dir中,所以当子类的属性和方法与父类的属性和方法私有时,
三 访问及修改类的私有属性和私有方法
通过私有化属性和方法,类可以保护它们。但是当外部需要被访问和改变时会发生什么呢?就像电视机一样,电脑也是对外提供固定接口的。
以上,虽然我们可以以类名()的形式访问一个类的私有属性和私有方法。_ class name _ _ attribute(实例属性)或类名。_ class name _ _ attribute (class属性),这是违背编程规范的,也是不支持的,就像它不会打开电视机来操作一样。
正确对类的私有属性和私有方法进行访问修改的一般有两种发方法,如下:
1. 自定义公有方法
D类():
__name='张三'
def __init__(self):
自我。_ _年龄=23岁
自我。__luange='python '
def __method(自我):
Print('我叫{},今年{}岁,我喜欢{}。'。格式(自我。__name,self。_ _年龄,自我。_ _栾格))
定义获取值(自身):
回归自我。__name,self。_ _年龄,自我。_ _栾格
def get_method(self):
自我。_ _方法()
def set_value(自我,姓名,年龄,乱格):
自我。__name,self。_ _年龄,自我。__luange=姓名、年龄、luange
if __name__=='__main__ ':
d=D()
#通过get_value方法访问私有属性
print(d.get_value())
#通过get_method方法访问私有方法
打印('=' * 30)
get_method()
#通过set_value方法修改私有属性
打印('='*30)
print(d.get_value())
D.set_value(《王子》,25,《Linux》)
print(d.get_value())
get_method()
输出结果:
(《张三》,23,“蟒蛇”)
==============================
我的名字叫张三。我今年23岁。我喜欢python。
==============================
(《张三》,23,“蟒蛇”)
(《王子》,25,《Linux》)
我叫王二麻子,今年25岁,喜欢Linux。
如你所见,我们可以通过自定义get_value()、get_method()和set_value()方法来访问和修改私有属性和私有方法。
2. property
property一般有两个作用,如下:
作为装饰者,@property将类的方法变成只读的类属性。属性重新实现属性的getter和setter方法。
来看看下面这个E类,如下:
E类():
__name='张三'
def __init__(self):
自我。_ _年龄=23岁
自我。__luange='python '
def __method(自我):
Print('我叫{},今年{}岁,我喜欢{}。'。格式(自我。__name,self。_ _年龄,自我。_ _栾格))
定义获取值(自身):
回归自我。_ _名称
定义集合值(自身,名称):
自我。__name=name
getValue=property(获取值,设置值)
@属性
def get_method(self):
自我。_ _方法()
if __name__=='__main__ ':
e=E()
#访问
打印(电子获取价值)
获取方法
#修改
E.getValue='王2 '
打印(电子获取价值)
结果:
张三
我的名字叫张三。我今年23岁。我喜欢python。
王二
正如您所看到的,在我们将get_value和set_value方法传递到属性中之后,类方法被转换为类属性并被赋给getValue变量。此时e.getValue为只读,即get_value方法,e. value='王二'为修改,即get_value方法。类似地,通过@propert,get_method方法变成了一个属性。
下面的属性重新实现了一个属性的getter和setter方法,它不同于上面的方法,比上面的方法更常用。
E类():
__name='张三'
def __init__(self):
自我。_ _年龄=23岁
自我。__luange='python '
def __method(自我):
Print('我叫{},今年{}岁,我喜欢{}。'。格式(自我。__name,self。_ _年龄,自我。_ _栾格))
@属性
定义名称(自身):
回归自我。_ _名称
@name.setter
定义名称(自己,名称):
自我。__name=name
if __name__=='__main__ ':
e=E()
#访问
打印(e.name)
#修改
打印('修改前:',e.name)
隔壁的老王
打印('已修改:',e.name)
输出结果:
张三
修改前:张三
改装后:隔壁老王
上面,name方法首先被发送给propert decorator进行修饰,然后调用修饰后的setter方法修改private属性。
关于Python面向对象打包细节的这篇文章就到这里了。有关Python打包的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。