python @property

本文探讨了Python中如何使用@property装饰器和私有属性保护类的成员变量,防止意外修改,确保数据安全。通过实例展示了如何定义只读、可写和可删除的属性。

在接触python时最开始接触的代码,取长方形的长和宽,定义一个长方形类,然后设置长方形的长宽属性,通过实例化的方式调用长和宽,像如下代码一样。

class Rectangle(object):
  def __init__(self):
    self.width =10
    self.height=20
r=Rectangle()
print(r.width,r.height)

此时输出结果为10 20
但是这样在实际使用中会产生一个严重的问题,init 中定义的属性是可变的,换句话说,是使用一个系统的所有开发人员在知道属性名的情况下,可以进行随意的更改(尽管可能是在无意识的情况下),但这很容易造成严重的后果。

class Rectangle(object):
  def __init__(self):
    self.width =10
    self.height=20
r=Rectangle()
print(r.width,r.height)
r.width=1.0
print(r.width,r.height)

以上代码结果会输出宽1.0,可能是开发人员不小心点了一个小数点上去,但是会系统的数据错误,并且在一些情况下很难排查。
这是生产中很不情愿遇到的情况,这时候就考虑能不能将width属性设置为私有的,其他人不能随意更改的属性,如果想要更改只能依照我的方法来修改,@property就起到这种作用(类似于java中的private)

class Rectangle(object):
  @property
  def width(self):
    #变量名不与方法名重复,改为true_width,下同
    return self.true_width
 
  @property
  def height(self):
    return self.true_height
s = Rectangle()
#与方法名一致
s.width = 1024
s.height = 768
print(s.width,s.height)

(@property使方法像属性一样调用,就像是一种特殊的属性)
此时,如果在外部想要给width重新直接赋值就会报AttributeError: can’t set attribute的错误,这样就保证的属性的安全性。
同样为了解决对属性的操作,提供了封装方法的方式进行属性的修改

class Rectangle(object):
  @property
  def width(self):
    # 变量名不与方法名重复,改为true_width,下同
    return self.true_width
  @width.setter
  def width(self, input_width):
    self.true_width = input_width
  @property
  def height(self):
    return self.true_height
  @height.setter
  #与property定义的方法名要一致
  def height(self, input_height):
    self.true_height = input_height
s = Rectangle()
# 与方法名一致
s.width = 1024
s.height = 768
print(s.width,s.height)

此时就可以对“属性”进行赋值操作,同样的方法还del,用处是删除属性,写法如下,具体实现不在赘述。

@height.deleter
def height(self):
    del self.true_height

总结一下@property提供了可读可写可删除的操作,如果像只读效果,就只需要定义@property就可以,不定义代表禁止其他操作。

### Python中`@property`装饰器的用法和实现方式 #### 1. `@property`装饰器的基本概念 `@property`装饰器用于将类中的方法转换为只读属性[^1]。通过这种方式,可以像访问普通属性一样调用方法,而无需显式地使用括号。 #### 2. 使用`@property`创建只读属性 以下是一个示例,展示如何使用`@property`装饰器创建只读属性: ```python class Human(object): def __init__(self, value): self._age = value @property def age(self): return self._age if __name__ == '__main__': peter = Human(18) print("The age of Peter is {}".format(peter.age)) # 输出:The age of Peter is 18 # peter.age = 20 # 如果尝试修改age属性,将会抛出 AttributeError ``` 在此示例中,`age`方法被`@property`装饰器修饰后,可以通过`peter.age`的方式访问,而无需使用`peter.age()`的形式[^1]。 #### 3. 使用`@property`实现可写属性 除了创建只读属性外,`@property`还可以与`@<attribute>.setter`结合使用,以实现可写属性。以下是一个示例: ```python class Human(object): def __init__(self, value): self._age = value @property def age(self): return self._age @age.setter def age(self, value): if value < 0: raise ValueError("Age cannot be negative") self._age = value if __name__ == '__main__': peter = Human(18) print("The age of Peter is {}".format(peter.age)) # 输出:The age of Peter is 18 peter.age = 25 # 修改年龄 print("The new age of Peter is {}".format(peter.age)) # 输出:The new age of Peter is 25 # peter.age = -5 # 尝试设置负值将抛出 ValueError ``` 在此示例中,`@age.setter`定义了`age`属性的设置逻辑,确保只能设置非负值[^1]。 #### 4. 使用`@property`实现删除属性功能 通过`@<attribute>.deleter`,可以定义删除属性时的行为。以下是一个示例: ```python class Human(object): def __init__(self, value): self._age = value @property def age(self): return self._age @age.setter def age(self, value): if value < 0: raise ValueError("Age cannot be negative") self._age = value @age.deleter def age(self): del self._age if __name__ == '__main__': peter = Human(18) print("The age of Peter is {}".format(peter.age)) # 输出:The age of Peter is 18 del peter.age # 删除 age 属性 # print(peter.age) # 尝试访问已删除的属性将抛出 AttributeError ``` 在此示例中,`@age.deleter`定义了删除`age`属性时的行为[^1]。 #### 5. `@property`装饰器的实现原理 `@property`装饰器本质上是一个描述符(descriptor),它通过重载`__get__`、`__set__`和`__delete__`方法来实现对属性的访问控制。当一个方法被`@property`装饰时,它会被替换为一个`property`对象,该对象管理对底层私有属性的访问[^1]。 以下是一个简单的`property`实现示例: ```python class Property: def __init__(self, fget=None, fset=None, fdel=None): self.fget = fget self.fset = fset self.fdel = fdel def __get__(self, instance, owner): if instance is None: return self if self.fget is None: raise AttributeError("unreadable attribute") return self.fget(instance) def __set__(self, instance, value): if self.fset is None: raise AttributeError("can't set attribute") self.fset(instance, value) def __delete__(self, instance): if self.fdel is None: raise AttributeError("can't delete attribute") self.fdel(instance) ``` 在这个实现中,`Property`类通过`__get__`、`__set__`和`__delete__`方法分别实现了对属性的获取、设置和删除操作[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值