3.23
Recordando a seção anterior
* args, kwargs **
-
* Args: * para os argumentos extras em uma posição atribuído ao argumento args
-
** kwargs, ** os argumentos extra-chave Dicionário atribuído para se tornar kwargs
-
Nos argumentos , * uma pausa
-
def index(*args,**kwargs): print(x,y) def wrapper(*args,**kwargs): # (1,2,34),{'x':1,'y':2} index(*args,**kwargs) # index(1,2,34,x=1,y=2) wrapper(1,2,34,x=1,y=2)
Neste formato, o formato dos argumentos para passar chamada intacta envoltório índice
Namespace e alcance
- A relação de espaço de nomes função aninhados definição de fase, isto é, para determinar quando a gramática detectada
- objeto de função
- Pode funcionar como argumento para outra função
- Ele pode ser usado como função de valores de retorno
definição de função aninhada
-
Uma função no pacote função
def outter(): def inner(): pass return inner # 不加括号,返回 inner的内存地址
função de fechamento
-
Built-in funções, e citou seu nome função externa
def f1(): x = 1 y = 2 z = 3 f1()
f1 namespace normal depois de terminar a chamada limpeza, mas se o próprio nome é uma referência para os outros lugares, e que sua referência contar ali, seu espaço de nome não serão recuperados
modo de passagem de parâmetros
-
os valores dos parâmetros formais como uma função de passe
-
Por meio de massa corpo de fecho como uma função do valor
def outter(x): def wrapper(): print(x) return wrapper # 处于局部 wrapper = outter(1) # 处于全局
-
Namespace: namespaces diferentes podem usar o mesmo nome, de modo que o local para a atribuição de função global da mesma função nome é possível
curso regular
decorador
o que é
-
Refere-se a um dispositivo ferramenta, você pode ser definida como uma função
-
refere-se decorativa para adicionar funcionalidade a outras ferramentas
-
Decorator:
A definição de uma ferramenta (classe, função, atualmente só aprender função), usado para adicionar funcionalidade para outra função
Por que você usa
Em um ambiente de desenvolvimento real para a expansão da função original, deve seguir o Aberto Princípio fechado , o software não pode ser facilmente modificado para funcionar on-line ou off
Aberto Fechado: Quer adicionar novas funcionalidades para uma função, mas não deseja alterar o código fonte para esta função
- Abra: aberto para ampliar a funcionalidade
- Fechado: modificar o código-fonte está fechada
Adicionar novos recursos à função original, pode envolver um número de lugares, se um erro, todo o erro de programa, levou a lançar um corpo.
Decorator não é modificado por objetos decorativos e chama o código-fonte sob a premissa, para adicionar funcionalidade para a função original
como
Exemplos
def index(x,y):
print('index %s %s'%(x,y))
index(111,222)
Há uma função normal, esta função agora gostaria de adicionar uma nova função, uma função de estatísticas de tempo de execução
Método a: a modificação do código fonte
-
Com um módulo de tempo
time.time
retorna o timestamp atual: A partir de 1970 para a hora atual em segundos -
funções executado antes time.time, após o fim do time.time prazo, função de tempo do fim função do tempo começando a diminuir é uma função do tempo de execução
import time def index(x,y): start = time.time() time.sleep(1) print('index %s %s'%(x,y)) end = time.time() print(end - start) index(111,222)
Será que implementar a função, não há nenhuma maneira de modificar a chamada de função, mas modificar o código fonte, não atendem o Aberto Princípio Closed
Método dois: antes e depois da instrução de chamada adicionadas
-
Antes e após a chamada com time.time
import time def index(x,y): time.sleep(1) print('index %s %s'%(x,y)) start = time.time() index(111, 222) end = time.time() print(end - start)
Quando uma necessidade de contar todas as vezes, antes e após as chamadas para adicionar este algumas linhas de código para conseguir sem alterar o código fonte, sem alterar a forma como as chamadas, mas em muitos lugares precisar esta nova funcionalidade, você precisa repetir isso para escrever algumas palavras declaração, o código é redundante, impróprio
Solução: decorador
-
Use fechamentos de função para resolver o problema da redundância de código, mas é chamado a tornar-se invólucro (), eo índice é escrito 111.222 mortos
import time def index(x,y): time.sleep(1) print('index %s %s'%(x,y)) def wrapper(x,y): start = time.time() index(111, 222) end = time.time() print(end - start) wrapper()
-
Melhorou 1, não escreva o invólucro morto:
index(x,y) ... wrapper(111,222)
-
Melhorou 2, **, você pode passar vários parâmetros, parâmetros de gravação vivos :
def index(x,y,z): ... def wrapper(*args,**kwargs): ... index(*args,**kwargs) wrapper(111,222,33,444)
-
Melhorou 3: invólucro Prefere índice apenas uma função decorativa, todas as funções podem ser decorados queria: a necessidade de passar para a função de invólucro como um parâmetro, mas o parâmetro não pode ser passado nesta função: o uso da função de fechamento para a função como um argumento, a função para gravar ao vivo
def outter(func): # 把要装饰的函数当作参数传给装饰器的包 def wrapper(*args,**kwargs): func(*args,**kwargs) return wrapper def index(x,y): print(x,y) f = outter(index) # 实际上是运行了wrapper,wrapper中的func实际上是调用时当作参数传入的函数 f(1,2)
Resolvido sem alterar o código fonte, escrever assunto morto, mas também mudou a forma como as chamadas
-
Final: não mudar a forma como as chamadas
Nomeado função melhorada com o nome da função original de perpetrar uma fraude
index = outter(index) index(1,2)
resumo de métodos
-
Os elementos decorativos feitos função de fechamento
-
Decorado no pacote de funcionar como um parâmetro passado funções aninhadas
-
função de fechamento é decorado com o pacote para a função de objeto, a função original dos parâmetros recebidos
-
Pacote função devolve uma função da função aninhada dos mesmos
-
Renomeado, perpetrar uma fraude
index = outter(index) index()
Para conseguir o efeito final: os reais
Esta abordagem tem a função retorna originais um valor no momento do problema: A função original foi substituída por uma função de invólucro, ligue para o índice é de fato chamando invólucro, enquanto o invólucro não retorna um valor, é necessário permitir o retorno do valor de retorno da função embalagem original
melhorando em última análise,
No decorador, o valor de retorno retornado pela função original deve ter
def outter(func): # 把要装饰的函数当作参数传给装饰器的包
def wrapper(*args,**kwargs):
func(*args,**kwargs)
res = func(*args,**kwargs)
return res # wrapper函数原函数的运行结果
return wrapper # 包函数在偷梁换柱的时候返回内嵌函数的函数体
def index(x,y):
print(x,y)
index = outter(index)
index(1,2)
Finalmente chegou, chamar o mesmo caminho, o mesmo código fonte, o valor de retorno é o mesmo, para alcançar os reais
açúcar sintático @ name decorador
Cada função decorativa a ser perpetrar uma fraude no nome função original
-
index = outter(index) index(1,2)
Há declarações sobre esta sintaxe simples: Escrever em uma linha separada é diretamente acima dos objetos decorativos @装饰器名字
, python automaticamente dar-lhe perpetrar uma fraude
-
def timmer(): # 装饰器必须在被装饰函数的上面 ... @timmer # 相当于帮你做了 index = timmer(index) def index(): ...
-
Decorador precisa ser colocado em cima do decorador , ou para executar @ esta linha de código, decorador ainda não foi definida, um erro
-
Uma função pode ser sobreposta pluralidade de decorador
ordem de carregamento:
@deco1 # deco1.wrapper的内存地址 = deco1(index) @deco2 # deco2.wrapper的内存地址 = deco2(index) @deco3 # deco3.wrapper的内存地址 = deco3(index) def index(): ...
resumo
O modelo básico
def outter(func):
def wrapper(*args,**kwargs):
res = func()
# 新功能
...
return res
return wrapper
@outter
def index(x,y):
# 原功能
...
index(x,y)
Isso está ficando um modelo, a função original escreve índice, novos recursos invólucro escritos, você recebe um decorador completa sem argumentos