Notas Python 05 (uso de decoradores)

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 @propertysão os seguintes:

  1. Encapsulamento e ocultação de detalhes de implementação : Ao usar@propertydecoradores, 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.

  2. 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.

  3. Calculando valores de propriedade : você  pode @propertyadicionar lógica ao método para calcular o valor da propriedade . Isso permite gerar propriedades dinamicamente conforme necessário, sem precisar armazenar dados adicionais.

  4. Validação e proteção de propriedades : @propertyos métodos permitem validar e proteger os valores das propriedades antes de defini-los . Você pode @propertyadicionar lógica de validação no método setter para garantir que o valor da propriedade atenda a determinadas condições.

  5. 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

*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

@staticmethode 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 é selfou cls, 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 é clsusado 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)

Acho que você gosta

Origin blog.csdn.net/March_A/article/details/133431242
Recomendado
Clasificación