Python pas pratique - écrire un décorateur en une ligne

Récemment, avec un collÚgue de travail, ils ont soutenu qu'il était impossible d'écrire un décorateur de cache en 4 lignes, j'ai soutenu que c'était possible. Tout a commencé avec 4 lignes, s'est terminé par une programmation fonctionnelle avec un tas d'expressions lambda sur une ligne et un décorateur sur une ligne.





Avertissement

Un tel code ne se retrouve pas dans mes projets ou les projets de mon équipe, et tout ce qui est décrit ci-dessous a été écrit dans le cadre d'une étude académique. Je comprends qu'un avantage important du langage de programmation python est sa lisibilité. L'auteur des substances psychotropes n'a utilisé que du café lors de la rédaction de cet article.





Prologue

Au dĂ©part, l'idĂ©e d'Ă©crire un dĂ©corateur en 4 lignes ne m'a pas touchĂ©. C'Ă©tait juste amusant d'Ă©crire un dĂ©corateur. Mais dans le processus, l'intĂ©rĂȘt sportif a prĂ©valu. Tout a commencĂ© avec un simple dĂ©corateur de cache.





data = {}  #     

def decor_cache(func):
  
    def wrapper(*args):
        #        
        #     
        key = f"{func.__name__}{args}" 
        #       
        if args in data:
            return data.get(key)
        else:
            #   
            response = func(args) #     
            data[key] = response #   
            return response
  
    return wrapper
      
      



Maintenant une tùche de 18 lignes de code, 11 si vous supprimez les espaces et les commentaires, faites 4 lignes. La premiÚre chose qui vient à l'esprit est d'écrire la construction if
 else en une seule ligne.





data = {}  #     

def decor_cache(func):
  
    def wrapper(*args):
        #        
        #     
        key = f"{func.__name__}{args}"
        if not args in data
            #   
            response = func(args) #     
            data[key] = response #   
        return data.get(key) if args in data else response
     
    return wrapper
      
      



Nous avons maintenant 15 lignes de code contre 18, et une autre si elle est apparue, ce qui crée une charge de calcul supplémentaire, mais aujourd'hui nous n'allons pas améliorer les performances. Ajoutons de l'entropie et du copier-coller à ce monde et simplifions la variable clé.





data = {}  #     

def decor_cache(func):
  
    def wrapper(*args):
        if not args in data
            #   
            response = func(args) #     
            data[f"{func.__name__}{args}"] = response #   
        return data.get(f"{func.__name__}{args}") if args in data else response
     
    return wrapper
      
      



12 , 8 . , 4 , .  —  callable (). lambda! wrapper lambda —  . "", . 





data = {}  #     

def decor_cache(func):
  cache = labda *args: data.get(f"{func.__name__}{args}") if args in data else data[f"{func.__name__}{args}"] = func(args) 
  
  return labda *args: cache(*args) if cache(*args) else data.get(f"{func.__name__}{args}")
      
      



! 4 ,  — . lambda , lambda . lambda : . 





lambda . lambda lambda , , lambda , lambda .





, ,  —  lambda . , . . . - lambda . lambda . 





, or. , , True False. . python . memory.update({f"{func.name}_{args[0]}": func(args[0])}) None update None False , memory. tupla, , tuple .





data = {}  #     

def decor_cache(func):
    return lambda *args: memory.get(f"{func.__name__}_{args[0]}") if f"{func.__name__}_{args[0]}" in memory else (lambda: memory.update({f"{func.__name__}_{args[0]}": func(args[0])}) or args[0])()

      
      



, lambda . , decorator_cache, lambda , . 





data = {}  #     

decor_cache = lambda func: lambda *args: memory.get(f"{func.__name__}_{args[0]}") if f"{func.__name__}_{args[0]}" in memory else (lambda: memory.update({f"{func.__name__}_{args[0]}": func(args[0])}) or args[0])()
      
      



, , . , data. ... 10 , python globals().





 globals()  , . ( —  ,  —  ). , . , :





globals().update({“memory”: {}})







get:





globals().get(“memory”)







, .





decor_cache = lambda func: lambda *args: globals().get("memory").get(f"{func.__name__}_{args[0]}") if f"{func.__name__}_{args[0]}" in globals().get("memory") else (lambda : globals().get("memory").update({f"{func.__name__}_{args[0]}": func(args[0])}) or args[0])()
      
      



, . , , , lambda , .





. , . . , , .





, lambda .








All Articles