property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
@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)
将一个类的函数定义成特性以后,对象再去使用的时候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
装饰器可以提供更好的封装性、访问控制、可兼容性、代码一致性和易用性,以及对属性修改过程的控制能力。它是一种有效的编程技术,有助于编写高质量、可维护的代码。