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
装饰器可以提供更好的封装性、访问控制、可兼容性、代码一致性和易用性,以及对属性修改过程的控制能力。它是一种有效的编程技术,有助于编写高质量、可维护的代码。