【 1 】什么是property
-
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
【 2 】使用方法和具体实例
面向对象的装饰器是一种在面向对象编程中用于修改类或方法行为的技术。装饰器提供了一种灵活的方式。可以在不修改原始类或方法的情况下, 动态的添加额外的功能或修改其行为。
在Python中, 装饰器通常以函数的形式存在。当应用于类或方法时, 装饰器将被调用,并且可以对目标或方法进行修改或扩展。
面向对象的装饰器可以用于以下几个方面:
-
类装饰器: 类装饰器用于修改或扩展整个类的行为。它接收一个类作为参数,并返回修改后的类。类装饰器可以用于添加类级别的属性、修改方法的行为、扩展类的功能等
-
方法装饰器: 方法装饰器用于修改单个方法的行为。它接收一个方法作为参数,并返回修改后的方法。方法装饰器可以用于添加额外的逻辑、实现缓存、实现权限控制登。
-
属性装饰器: 属性装饰器用于修改类的属性的行为。它接收一个属性名作为参数,并返回修改后的属性描述。属性装饰器可以用于验证属性值、实现延迟加载等。、
-
@property
装饰器将name
方法转换为一个只读属性。当我们通过person.name
的方式获取属性值时,实际上是调用了name
方法,并返回其结果。 -
@name.setter
装饰器将name
方法转换为一个可写属性。当我们通过person.name = value
的方式设置属性值时,实际上是调用了name
方法,并将value
作为参数传递给它。 -
@name.deleter
装饰器将name
方法转换为一个可删除属性。当我们使用del person.name
的方式删除属性时,实际上是调用了name
方法。
-
通过使用面向对象的装饰器,我们可以在不修改原始类或方法代码的情况下,动态地扩展其功能或修改其行为。
需要注意的是,在使用装饰器时,应该遵循装饰器的规范,并确保装饰器函数的签名和返回值与被装饰的类或方法一致,以确保正确的行为修改。
类装饰器:
class MyClass:
@classmethod
def class_method(cls):
print("This is a class method.")
print("Class name:", cls.__name__)
# 调用类方法,无需创建类的实例
MyClass.class_method()
# This is a class method.
# Class name: MyClass
# 类装饰器的应用
#
user = {
'username': 'mao',
'password': 123
}
def add_method(cls):
def new_method(self):
username = input('请输入你的账号:')
password = input('请输入你的密码:')
if username in user['username'] and int(password) == user["password"]:
print('登陆成功!')
else:
print('用户名或密码错误!')
cls.new_method = new_method # 添加新方法到类中
return cls
@add_method
class MyClass:
def existing_method(self):
print("Existing method in the class")
if __name__ == '__main__':
obj = MyClass()
obj.existing_method() # 输出:Existing method in the class
obj.new_method()
方法装饰器:
import random
user = {'username': 'mao',
'password': 123}
def get_code():
result = ""
for _ in range(4):
random_int = str(random.randint(0, 9))
temp = random.choice([random_int])
result += temp
return result
res = get_code()
def outter(func):
def inner(*args, **kwargs):
print('登陆之前先输入验证码!')
res = func(*args, **kwargs)
username = input('请输入你的账号!')
password = input('请输入你的密码:')
if user['username'] == username and user['password'] == int(password):
print('登陆成功!')
else:
print('用户密码错!')
return res
return inner
class MyClass:
@outter
def my_method(self):
# 生产验证码并提示输入
code = get_code()
print(f'请输入下面的验证码进行注册:{code}')
input_code = input('请输入你的验证码!')
if input_code != code:
print('验证码错误! ')
return
obj = MyClass()
obj.my_method()
# 添加课程
import random
user = {'username': 'mao', 'password': 123}
def get_code():
result = ""
for _ in range(4):
random_int = str(random.randint(0, 9))
temp = random.choice([random_int])
result += temp
return result
def verify_code(func):
def wrapper(*args, **kwargs):
code = get_code()
print(f'请输入下面的验证码进行操作:{code}')
input_code = input('请输入你的验证码!')
if input_code != code:
print('验证码错误!')
return
result = func(*args, **kwargs)
return result
return wrapper
def outter(func):
def inner(*args, **kwargs):
print('登陆之前先输入验证码!')
username = input('请输入你的账号!')
password = input('请输入你的密码:')
if user['username'] == username and user['password'] == int(password):
print('登陆成功!')
res = func(*args, **kwargs)
return res
else:
print('用户密码错!')
exit()
return inner
class Login:
@verify_code
def add_course(self):
course_name = input('请输入课程名称:')
print(f'成功添加课程:{course_name}')
@outter
def login(self):
...
obj = Login()
obj.login() # 调用登陆方法
obj.add_course() # 调用添加课程方法
属性装饰器:
# 属性装饰器
class MyClass:
def __init__(self):
self._name = None
# 我们在这里name设置为受保护属性
@property
# 这里的property是将我们的_name重新设定为可读属性
def name(self):
return self._name
@name.setter
# 将name方法转换为一个可写属性。
def name(self, value):
self._name = value.capitalize()
obj = MyClass()
# 使用属性装饰器设置属性值
obj.name = 'john doe'
# 使用属性装饰器获取属性值
print(obj.name) # John doe
小试牛刀:
class User:
def __init__(self, username, password):
self.username = username
self.password = password
@property
def username(self):
return self._username
@username.setter
def username(self, value):
if not isinstance(value, str):
raise ValueError('用户名必须是字符串!')
self._username = value
@property
def password(self):
return self._password
@password.setter
def password(self, value):
if not isinstance(value, str):
raise ValueError('密码必须是字符串!')
self._password = value
def login(self, username, password):
if username == self.username and password == self.password:
print('登陆成功!')
else:
print('登陆失败!')
user = User('admin', '12186')
username = input('请输入你的账号: >>>>>>')
password = input('请输入你的密码: >>>>>>')
user.login(username, password)
【3】为什么要用property
-
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
-
面向对象的封装有三种方式:
-
【public】
-
这种其实就是不封装,是对外公开的
-
-
【protected】
-
这种封装方式对外不公开
-
但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
-
-
【private】
-
这种封装对谁都不公开
-
-
使用property
的主要目的是为了实现对类的属性访问和修改的控制,以提供更加灵活和可靠的代码。
class Rctena:
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 value > 0:
self._width = value
else:
raise ValueError('宽度必须大于0')
@property
def height(self):
return self._height
@height.setter
def height(self, value):
if value > 0:
self._height = value
else:
raise ValueError('高度必须大于0')
x = Rctena(10,6)
print(x.width,x.height)
x.height = 15
print(x.height) # 输出:15
x.height = -5 #ValueError: 高度必须大于0
代码更加自然和简洁,同时提高了代码的可读性和可维护性。
总之,使用
property
装饰器可以提供更好的封装性、访问控制、可兼容性、代码一致性和易用性,以及对属性修改过程的控制能力。它是一种有效的编程技术,有助于编写高质量、可维护的代码。