您当前所在位置:幽门梗阻 > 病种百科 > Python类和对象4

Python类和对象4

白癜风中医诊疗倡导者 https://m-mip.39.net/baidianfeng/mipso_5941838.html
Pythonproperty()函数:定义属性Python

property装饰器详解Python封装机制及实现方法Python封装底层实现原理详解Pythonproperty()函数:定义属性

正常情况下,类包含的属性应该是隐藏的,只允许通过类提供的方法来间接实现对类属性的访问和操作。因此,在不破坏类封装原则的基础上,为了能够有效操作类中的属性,类中应包含读(或写)类属性的多个getter(或setter)方法,这样就可以通过“类对象.方法(参数)”的方式操作属性,例如:

classCLanguage:

#构造函数

def__init__(self,name):

self.name=name

#设置name属性值的函数

defsetname(self,name):

self.name=name

#访问nema属性值的函数

defgetname(self):

returnself.name

#删除name属性值的函数

defdelname(self):

self.name="xxx"

clang=CLanguage("C语言中文网")

#获取name属性值

print(clang.getname())

#设置name属性值

clang.setname("Python教程")

print(clang.getname())

#删除name属性值

clang.delname()

print(clang.getname())

运行结果为:

C语言中文网Python教程xxx

可能有读者觉得,这种操作类属性的方式比较麻烦,更习惯使用“类对象.属性”这种方式。庆幸的是,Python中提供了property()函数,可以实现在不破坏类封装原则的前提下,让开发者依旧使用“类对象.属性”的方式操作类中的属性。property()函数的基本使用格式如下:

属性名=property(fget=None,fset=None,fdel=None,doc=None)

其中,fget参数用于指定获取该属性值的类方法,fset参数用于指定设置该属性值的方法,fdel参数用于指定删除该属性值的方法,最后的doc是一个文档字符串,用于说明此函数的作用。

注意,在使用property()函数时,以上4个参数可以仅指定第个、或者前2个、或者前3个,当前也可以全部指定。也就是说,property()函数中参数的指定并不是完全随意的。

例如,修改上面的程序,为name属性配置property()函数:

classCLanguage:

#构造函数

def__init__(self,n):

self.__name=n

#设置name属性值的函数

defsetname(self,n):

self.__name=n

#访问nema属性值的函数

defgetname(self):

returnself.__name

#删除name属性值的函数

defdelname(self):

self.__name="xxx"

#为name属性配置property()函数

name=property(getname,setname,delname,指明出处)

#调取说明文档的2种方式

#print(CLanguage.name.__doc__)

help(CLanguage.name)

clang=CLanguage("C语言中文网")

#调用getname()方法

print(clang.name)

#调用setname()方法

clang.name="Python教程"

print(clang.name)

#调用delname()方法

delclang.name

print(clang.name)

运行结果为:

Helponproperty:指明出处C语言中文网Python教程xxx

注意,在此程序中,由于getname()方法中需要返回name属性,如果使用self.name的话,其本身又被调用getname(),这将会先入无限死循环。为了避免这种情况的出现,程序中的name属性必须设置为私有属性,即使用__name(前面有2个下划线)。

有关类属性和类方法的属性设置(分为共有属性、保护属性、私有属性),后续章节会做详细介绍。

当然,property()函数也可以少传入几个参数。以上面的程序为例,我们可以修改property()函数如下所示

name=property(getname,setname)

这意味着,name是一个可读写的属性,但不能删除,因为property()函数中并没有为name配置用于函数该属性的方法。也就是说,即便CLanguage类中设计有delname()函数,这种情况下也不能用来删除name属性。同理,还可以像如下这样使用property()函数:

name=property(getname)#name属性可读,不可写,也不能删除

name=property(getname,setname,delname)#name属性可读、可写、也可删除,就是没有说明文档

Python

property装饰器详解

既要保护类的封装特性,又要让开发者可以使用“对象.属性”的方式操作操作类属性,除了使用property()函数,Python还提供了

property装饰器。通过

property装饰器,可以直接通过方法名来访问方法,不需要在方法名后添加一对“()”小括号。

property的语法格式如下:

propertydef方法名(self)代码块

例如,定义一个矩形类,并定义用

property修饰的方法操作类中的area私有属性,代码如下:

classRect:

def__init__(self,area):

self.__area=area

property

defarea(self):

returnself.__area

rect=Rect(30)

#直接通过方法名来访问area方法

print("矩形的面积是:",rect.area)

运行结果为:

矩形的面积为:30

上面程序中,使用@property修饰了area()方法,这样就使得该方法变成了area属性的getter方法。需要注意的是,如果类中只包含该方法,那么area属性将是一个只读属性。也就是说,在使用Rect类时,无法对area属性重新赋值,即运行如下代码会报错:

rect.area=90

print("修改后的面积:",rect.area)

运行结果为:

Traceback(mostrecentcalllast):File"C:\Users\mengma\Desktop\.py",line0,inmodulerect.area=90AttributeError:cantsetattribute

而要想实现修改area属性的值,还需要为area属性添加setter方法,就需要用到setter装饰器,它的语法格式如下:

方法名.setterdef方法名(self,value):代码块

例如,为Rect类中的area方法添加setter方法,代码如下:

area.setter

defarea(self,value):

self.__area=value

再次运行如下代码:

rect.area=90

print("修改后的面积:",rect.area)

运行结果为:

修改后的面积:90

这样,area属性就有了getter和setter方法,该属性就变成了具有读写功能的属性。除此之外,还可以使用deleter装饰器来删除指定属性,其语法格式为:

方法名.deleterdef方法名(self):代码块

例如,在Rect类中,给area()方法添加deleter方法,实现代码如下:

area.deleter

defarea(self):

self.__area=0

然后运行如下代码:

delrect.area

print("删除后的area值为:",rect.area)

运行结果为:

删除后的area值为:0

Python封装机制及实现方法

简单的理解封装(Encapsulation),即在设计类时,刻意地将一些属性和方法隐藏在类的内部,这样在使用此类时,将无法直接以“类对象.属性名”(或者“类对象.方法名(参数)”)的形式调用这些属性(或方法),而只能用未隐藏的类方法间接操作这些隐藏的属性和方法。就好比使用电脑,我们只需要学会如何使用键盘和鼠标就可以了,不用关心内部是怎么实现的,因为那是生产和设计人员该操心的。

注意,封装绝不是将类中所有的方法都隐藏起来,一定要留一些像键盘、鼠标这样可供外界使用的类方法。

那么,类为什么要进行封装,这样做有什么好处呢?首先,封装机制保证了类内部数据结构的完整性,因为使用类的用户无法直接看到类中的数据结构,只能使用类允许公开的数据,很好地避免了外部对内部数据的影响,提高了程序的可维护性。除此之外,对一个类实现良好的封装,用户只能借助暴露出来的类方法来访问数据,我们只需要在这些暴露的方法中加入适当的控制逻辑,即可轻松实现用户对类中属性或方法的不合理操作。并且,对类进行良好的封装,还可以提高代码的复用性。

Python类如何进行封装?

和其它面向对象的编程语言(如C++、Java)不同,Python类中的变量和函数,不是公有的(类似public属性),就是私有的(类似private),这2种属性的区别如下:

public:公有属性的类变量和类函数,在类的外部、类内部以及子类(后续讲继承特性时会做详细介绍)中,都可以正常访问;

private:私有属性的类变量和类函数,只能在本类内部使用,类的外部以及子类都无法使用。

但是,Python并没有提供public、private这些修饰符。为了实现类的封装,Python采取了下面的方法:

默认情况下,Python类中的变量和方法都是公有(public)的,它们的名称前都没有下划线(_);

如果类中的变量和函数,其名称以双下划线“__”开头,则该变量(函数)为私有变量(私有函数),其属性等同于private。

除此之外,还可以定义以单下划线“_”开头的类属性或者类方法(例如_name、_display(self)),这种类属性和类方法通常被视为私有属性和私有方法,虽然它们也能通过类对象正常访问,但这是一种约定俗称的用法。

注意,Python类中还有以双下划线开头和结尾的类方法(例如类的构造函数__init__(self)),这些都是Python内部定义的,用于Python内部调用。

例如,如下程序示范了Python的封装机制:

classCLanguage:

defsetname(self,name):

iflen(name)3:

raiseValueError(名称长度必须大于3!)

self.__name=name

defgetname(self):

returnself.__name

#为name配置setter和getter方法

name=property(getname,setname)

defsetadd(self,add):

ifadd.startswith("


转载请注明:http://www.zpwkh.com/bzbk/14693.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了

  • 当前时间: