禁止随意设置属性
需求
考虑这样一种情况,在某一个类中,有一个属性我们不希望别人随便设置,因为这可能会造成很大的麻烦:
1 2 3 4 5 6 7 8 9 10 11 | class Rectangle: def __init__( self , width, height): self .width = width self .height = height def calculate_area( self ): return self .width * self .height r = Rectangle( 3 , 4 ) print (r.calculate_area()) |
在这种情况下,长度和宽度都应该是数字类型的,而如果有人在这个过程中修改了这个属性,那么就会导致错误。
1 2 3 | r = Rectangle( 3 , 4 ) r.width = "3" print (r.calculate_area()) # 结果为3333,明显不是我们希望的结果 |
私有属性
为了避免他人随意访问,我们可以将其设置为私有属性,通常可以添加1个或者2个下划线。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Rectangle: def __init__( self , width, height): # 一个下划线通常表明了,这个属性不应该随意使用,但是不起实际作用 self ._width = width # 两个下划线表明了,这个属性会触发名称重整,但是也并非真正的私有 self .__height = height r = Rectangle( 3 , 4 ) print (r._width) # 双下划线最终会重整为_类名__属性名的形式 print (r._Rectangle__height) |
需要注意的是,由于python中没有真正的私有属性,所以,这两种设置方法都不能完全起到作用,但是一般而言,两个下划线是更好的,因为可以触发名称重整。
提供访问方法
在这种情况下,为了避免他人随意设置属性,因此需要提供专门的访问方法。
1 2 3 4 5 6 7 8 9 | class Rectangle: def __init__( self , width, height): self .set_width(width) self .set_height(height) def set_width( self , width): if not isinstance (width, ( int , float )): raise ValueError( "width must be a number." ) if width |
但是这样的使用方法并不方便,因此,在python中,一个更好的使用方法是通过property。
property的详细介绍
基本语法
基本语法实现是通过property的内置函数完成的
1 2 3 4 5 6 7 8 9 10 11 | class MyClass: def __init__( self , value): self .value = value # get方法 def get_value( self ): return self .__value # set方法 def set_value( self , value): if value |
使用装饰器
1 2 3 4 5 6 7 8 9 10 11 | class MyClass: def __init__( self , value): self .value = value @property def value( self ): return self .__value @value .setter def value( self , value): if value |
与基本语法的版本效果是相同的
常见应用
数据隐藏与封装
property装饰器允许像访问和操作普通一样属性进行操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Rectangle: def __init__( self , width, height): self .width = width self .height = height @property def width( self ): return self .__width @width .setter def width( self , value): if not isinstance (value, ( int , float )): raise ValueError( "width must be a number." ) if value |
设置只读属性
通过property,可以设置一个属性只允许读取,不允许修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class Person: def __init__( self , name): self .__name = name @property def name( self ): return self .__name # 初始化的时候可以设置名字 p = Person( "sagegrass" ) # 名字可以正常被访问 print (p.name) # 名字不可以被修改,AttributeError: can't set attribute 'name' p.name = "xxx" |
一般来说,这样设置已经足够保证属性只读,但是极特殊的情况下,仍然可以通过p._Person__name进行修改,
不过通常无需额外关注这一问题。
动态计算
关于一开始的例子,我们使用calculate_area进行面积的计算,但是,通过property就可以将area设置为一个属性,进行动态的计算
1 2 3 4 5 6 7 | class Rectangle: def __init__( self , width, height): self .width = width self .height = height def calculate_area( self ): return self .width * self .height |
使用property属性,修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Rectangle: def __init__( self , width, height): self .width = width self .height = height @property def area( self ): return self .width * self .height r = Rectangle( 3 , 4 ) print (r.area) r.width = 5 print (r.area) |
以上就是python使用property完成数据隐藏封装与校验的详细内容,更多关于python property数据隐藏封装与校验的资料请关注IT俱乐部其它相关文章!