@property
是 Python 中用于创建属性的装饰器。它的作用是将一个类方法转换为类属性,从而可以像 访问属性一样访问该方法,而不需要使用函数调用的语法。使用 @property
主要有以下好处:
封装性和隐藏实现细节:通过使用 @property
装饰器,你可以将属性的访问封装在方法内部,从而隐藏了实现细节。这有助于防止用户直接访问和修改类的内部状态,提高了类的封装性。
属性访问的一致性:将方法转换为属性后,可以使用点运算符 (.) 来访问属性,与直接访问属性时的语法一致。这增强了代码的可读性和一致性。
计算属性值:你 可以在 @property
方法中添加逻辑来计算属性的值。这允许你根据需要动态生成属性,而不必存储额外的数据。
属性验证和保护:@property
方法允许你在 设置属性值之前进行验证和保护。你可以在 @property
的 setter 方法中添加验证逻辑,确保属性值符合特定条件。
适用于重构:如果你决定更改属性的实现方式,可以在不更改类的用户代码的情况下重构 @property
方法。这有助于维护代码的兼容性。
class Person:
def __init__(self, gender):
self.__gender = gender # 私有的
@property # 装饰器
def gender(self):
return self.__gender
@gender.setter
def gender(self, value):
if value != 'boy' and value != 'girl':
raise ValueError('Gender must be boy or girl')
else:
self.__gender = value
if __name__ == '__main__':
p = Person('boy')
print(p.gender) # boy
p.gender = 'girl' # @gender.setter
print(p.gender) # girl
p.gender = 'other' # @gender.setter
print(p.gender) # ValueError: Gender must be boy or girl
def logger(func): # 被装饰的函数作为方法的参数
def class_time():
print('二、四、六晚上上课')
print('_' * 30)
func()
print('_' * 30)
print('大概下课时间,22:30')
return class_time
# 函数式
@logger
def work():
print('老师在上课')
@logger
def work2():
print('学生不想上课')
if __name__ == '__main__':
work()
print('\n')
work2()
1 *args, **kwargs # 自定义位置参数和关键字参数
from functools import wraps
def main_logger(time_key='二、四、六晚上八点', end_time='21:30'):
def logger(func):
@wraps(func)
def class_time(*args, **kwargs):
print('上课时间:', time_key)
func(*args, **kwargs)
print('下课时间:', end_time)
return class_time
return logger
# 核心功能
@main_logger()
def work():
print('三月要上课啦!')
@main_logger(time_key='一、三、五晚上')
def work2():
print('老子今天不上课')
@main_logger()
def work4(name, subject):
print(f'{name}在上课 {subject}课程')
if __name__ == '__main__':
# work()
# work2()
work4('march', 'dj')
class Logs:
def __init__(self, start_time='二、四、六晚上20:00', end_time='21:30'):
self.start_time = start_time
self.end_time = end_time
# 重写object类中 call 方法
def __call__(self, func): # func是被装饰的函数
def class_time(*args, **kwargs):
print('上课时间:', self.start_time)
func(*args, **kwargs)
print('下课时间:', self.end_time)
return class_time
@Logs() # 类对象装饰
def work(name, subject):
print(f'{name}在上 {subject}')
if __name__ == '__main__':
work('your', '奇奇怪怪的课')
functools.partial:需要传入原函数和需要传入的参数
下面两种方式等价:
import functools
int3 = functools.partial(int, base=16)
print(int3('abd'))
直接写:
def int2(num, base=16):
return int(num, base)
print(int2('abd'))
@staticmethod
和 @classmethod
是 Python 中用于定义静态方法和类方法的装饰器,它们有不同的作用和用法。
@staticmethod
:
self
或 cls
,而是一个普通参数,用于传递方法所需要的数据。@classmethod
:
cls
,用于表示类本身,可以访问类的属性和调用其他类方法。class Person:
def __init__(self, name, age):
self.name = name
self.age = age
if __name__ == '__main__':
p = Person('march', 20)
print('name:', p.name)
print('age:', p.age)
p.gender = 'boy' # 动态添加属性
print('gender:', p.gender)
def fun():
print('我是一个普通函数,即将成为一个实例 方法')
# 动态添加方法
p.show = fun
p.show()
def fun2(self):
print('我也是一个普通函数,第一个参数是self,类成员方法的第一个参数就是self')
# 第二种添加方式
p.show2 = types.MethodType(fun2, p)
p.show2()
@staticmethod
def static_func():
print('马上成为Person类中的静态方法, staticmethod')
# 动态添加静态方法, 通过类名调用
Person.sf = static_func
Person.sf()
@classmethod
def class_func(cls):
print('马上成为Person类中的类方法, class_method')
# 动态添加类方法
Person.cf = class_func
Person.cf()
# 动态添加类方法
print(dir(Person))
print(dir(p))
__slots__:现在属性的添加
class Person:
__slots__ = ('name', 'age')
def __init__(self, name, age):
self.name = name
self.age = age
if __name__ == '__main__':
p = Person('march', 20)
p.gender = 'boy' # __slots__ = ('name', 'age') 限制可以添加的属性
print('gender:', p.gender)