O uso de um decorador (@property)
@property
É um decorador usado para criar propriedades em Python. Sua função é converter um método de classe em um atributo de classe, para que o método possa ser acessado como um atributo sem usar a sintaxe de uma chamada de função. Os principais benefícios do uso @property
são os seguintes:
-
Encapsulamento e ocultação de detalhes de implementação : Ao usar
@property
decoradores, você pode encapsular o acesso à propriedade dentro dos métodos, ocultando assim os detalhes da implementação. Isso ajuda a evitar que os usuários acessem e modifiquem diretamente o estado interno da classe, melhorando o encapsulamento da classe. -
Consistência de acesso à propriedade : Após converter um método em uma propriedade, você pode usar o operador ponto (.) para acessar a propriedade , consistente com a sintaxe ao acessar a propriedade diretamente. Isso melhora a legibilidade e a consistência do código.
-
Calculando valores de propriedade : você pode
@property
adicionar lógica ao método para calcular o valor da propriedade . Isso permite gerar propriedades dinamicamente conforme necessário, sem precisar armazenar dados adicionais. -
Validação e proteção de propriedades :
@property
os métodos permitem validar e proteger os valores das propriedades antes de defini-los . Você pode@property
adicionar lógica de validação no método setter para garantir que o valor da propriedade atenda a determinadas condições. -
Bom para refatoração : se você decidir alterar a forma como uma propriedade é implementada, poderá refatorar um método sem alterar o código do usuário da classe
@property
. Isso ajuda a manter a compatibilidade do código.
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
Dois decoradores personalizados
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()
Três parâmetros de decorador e parâmetros de função
1 *args, **kwargs # Parâmetros posicionais personalizados e parâmetros de palavras-chave
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')
4. Use objetos como decoradores
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', '奇奇怪怪的课')
Cinco funções parciais
functools.partial : Você precisa passar a função original e os parâmetros que precisam ser passados
Os dois métodos a seguir são equivalentes:
import functools
int3 = functools.partial(int, base=16)
print(int3('abd'))
Apenas escreva:
def int2(num, base=16):
return int(num, base)
print(int2('abd'))
Seis modificam dinamicamente o status da classe
@staticmethod
e são decoradores usados para definir métodos estáticos e métodos de classe em Python. Eles têm diferentes funções e usos. @classmethod
@staticmethod
:
- Métodos estáticos são métodos definidos em uma classe que não dependem de instâncias da classe ou do estado da classe.
- Geralmente é usado em situações onde o acesso às propriedades ou métodos da instância não é necessário e pode ser considerado uma função utilitária da classe.
- O primeiro parâmetro de um método estático geralmente não é
self
oucls
, mas um parâmetro comum usado para passar os dados exigidos pelo método.
@classmethod
:
- Um método de classe é um método definido em uma classe, mas não tem nada a ver com instâncias da classe, mas depende da própria classe.
- O primeiro parâmetro de um método de classe geralmente é
cls
usado para representar a própria classe, que pode acessar as propriedades da classe e chamar outros métodos de classe. - Os métodos de classe geralmente são usados como métodos de fábrica ou para realizar algumas operações na classe antes de criar uma instância.
6.1 Definir classes
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)
6.2 Adicionar atributos
p.gender = 'boy' # 动态添加属性
print('gender:', p.gender)
6.3 Método de adição dinâmica
def fun():
print('我是一个普通函数,即将成为一个实例 方法')
# 动态添加方法
p.show = fun
p.show()
def fun2(self):
print('我也是一个普通函数,第一个参数是self,类成员方法的第一个参数就是self')
# 第二种添加方式
p.show2 = types.MethodType(fun2, p)
p.show2()
6.4 Adicionar métodos estáticos dinamicamente
@staticmethod
def static_func():
print('马上成为Person类中的静态方法, staticmethod')
# 动态添加静态方法, 通过类名调用
Person.sf = static_func
Person.sf()
6.5 Adicionar métodos de classe dinamicamente
@classmethod
def class_func(cls):
print('马上成为Person类中的类方法, class_method')
# 动态添加类方法
Person.cf = class_func
Person.cf()
# 动态添加类方法
print(dir(Person))
print(dir(p))
6.6 Adicionando atributos de restrição
__slots__ : Agora a adição de atributos
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)