Python装饰器使用及内置@property 和 @.setter等方法

在Python中,当我们需要对函数进行内部引用时,使用@语法糖创建装饰器decorator可以让程序更加简洁,可读性更强。

不用装饰器

比如以下用户名校验函数

def login_user(username, password):
  print('Login success')

def user_check(func):
  def wrapper(username, password):
    if username != 'root':
      raise Exception("Permission denied")
    elif password != 'admin':
      raise Exception("Pass incorrect")
    else:
      return func(username, password)
  return wrapper

要想完成校验,我们需要采用如下调用方式:

login = user_check(login_user)
login('root', '123')

获得结果:

Traceback (most recent call last):
  File "/home/silan/test.py", line 16, in <module>
    login('root', '123')
  File "/home/silan/test.py", line 10, in wrapper
    raise Exception("Pass incorrect")
Exception: Pass incorrect

可以发现按照一般的调用方式,我们需要在正是调用前添加

login = user_check(login_user)

这和我们使用Python的一般习惯不符,所以此时我们可以使用装饰器来简化这一过程。

使用装饰器

我们对代码进行如下改动:

def user_check(func):
  def wrapper(username, password):
    if username != 'root':
      raise Exception("Permission denied")
    elif password != 'admin':
      raise Exception("Pass incorrect")
    elif len(password) < length:
      raise Exception("Password should have at least {} characters".format(length))
    else:
      return func(username, password)
  return wrapper

@ user_check #添加装饰器,@后跟随需要调用的函数名
def  New_login_user(username, password):
  print('Pass')

在正式调用时我们只需要运行

New_login_user('root', 'admin') # 结果:Pass

除此以外,定义装饰器时也可以传递参数。

还是使用之前的例子,我们添加一个密码长度验证功能,同时假设对应不同的场景,需要设定不同的密码长度。

def check(length):# length为调用时需要输入的长度
  def user_check(func):
    def wrapper(username, password):
      if username != 'root':
        raise Exception("Permission denied")
      elif password != 'admin':
        raise Exception("Pass incorrect")
      elif len(password) < length:# 添加长度验证
        raise Exception("Password should have at least {} characters".format(length))
      else:
        return func(username, password)
    return wrapper
  return user_check

@ check(6)# 正式调用时设定长度为6
def  New_login_user(username, password):
  print('Pass')

同样直接执行

New_login_user('root', 'admin')

# Exception: Password should have at least 6 characters

Python内置装饰器

除了自定义装饰器,Pyhton还有一些内置的装饰器,可以直接使用。

@property将方法转化为属性,只能读不能写,可以通过调用属性的方式来调用方法
@.setter与@property配合,出现在@property后,用于指定可以修改@property属性值的方法
@.deleter与@property配合,出现在@property后,用于指定可以清除@property属性值的方法
@classmethod类方法,可以通过这个方法传递类的属性和方法(不能传实例的属性和方法)
@staticmethod静态方法,与类方法类似,但是方法体中不能使用类或实例的任何属性和方法。静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护。

举个例子

class Student():
 
    def __init__(self):
        self._score = None
        
    @property
    def score(self):
        return self._score
    
    @score.setter
    def score(self, value):
        self._score = value
    
    @score.deleter
    def score(self):
        del self._score
 
if __name__ == "__main__":
    s = Student()
    print (s.score) # 通过@property读取self._score,结果:None
    s.score = 60 # 通过@.setter设置self._score
    print (s.score) # 结果:60
    del s.score # # 删除self._score属性
class Date(object):
  day = 0
  month = 0
  year = 0

  def __init__(self, year=0, month=0, day=0):
    self.day = day
    self.month = month
    self.year = year

  @classmethod # 第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法)
  def from_string(cls, date_as_string):
    year, month, day = date_as_string.split('-')
    date = cls(year, month, day)
    return date

  @staticmethod
  def is_date_valid(date_as_string):
    year, month, day = date_as_string.split('-')
    return int(year) <= 3999 and int(month) <= 12 and int(day) <= 31

date1 = Date.from_string('2012-05-10') # 使用类方法
print(date1.year, date1.month, date1.day) # 2012 05 10
is_date = Date.is_date_valid('2012-09-18') # 使用静态方法判断日期格式
print(is_date) # 格式正确 返回True

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
@propertyPython中的一个内置修饰符,用于将一个方法变成属性调用。在面向对象编程中,有时候我们希望通过调用对象的属性来获得或设置其值,而不是直接调用方法。这样可以使代码更加简洁和易读。 @property使用方式是,在需要被修饰的方法上方加上@property装饰符。这样,当我们调用对象的该方法时,就会像访问属性一样来访问。 @property修饰的方法通常用于获取属性的值,因此被称为getter方法。此外,我们还可以使用@property来定义setter方法,用于设置属性的值。 @property与getter和setter方法的原理是通过实现特殊的方法来实现的。 对于getter方法,@property将其装饰的方法转换为只读的属性。当我们通过调用该属性时,实际上调用的是被装饰的方法。 对于setter方法,@方法名.setter装饰器用来定义一个名字与被装饰方法相同的方法,并通过该方法来修改属性的值。当我们给该属性赋值时,实际上调用的是被装饰的setter方法。 通过getter和setter方法的配合,@property可以使我们在获取和设置属性值时更加灵活和方便。比如,我们可以在setter方法中进行属性值的校验和处理,确保属性值符合预期。 总结起来,@property提供了一种优雅和方便的方式来定义类的属性访问方法,使得我们可以像访问属性一样来调用这些方法。它的实现原理是通过装饰器和特殊的方法来实现的。这种方式使得代码更加简洁、易读,并且拥有更高的灵活性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值