2017-10-21 50 views
-3

Supposons que nous ayons une fonction:En python, comment faire un paramètre d'entrée pour fonctionner immuable?

import copy 

def demo_function(list_in) 
    list_out = copy.deepcopy(list_in) 
    list_in.append("howdy") 
    return list_out 

avis que nous joignons à list_in au lieu de list_out. Cependant, demo_function n'est pas réellement supposé modifier son entrée. Nous voulons imposer cela. Une erreur devrait être levée si quelqu'un modifie accidentellement list_in quelque part dans le corps de demo_function Comment pouvons-nous mettre en œuvre ce type de vérification d'erreur?

Ce qui suit est ma meilleure tentative, mais cela ne fonctionne pas. La chaîne "howdy" finit toujours par être ajoutée à list_in; aucune erreur est renvoyée

class Frozen(object): 
    # The Frozen class was developed by ActiveState Software Inc. 
    def __init__(self, value): 
     self._value = value 

    def __getattribute__(self, name): 
     if name == '_value': return super(Frozen, self).__getattribute__(name) 
     v = getattr(self._value, name) 
     return v if hasattr(v, '__hash__') else Frozen(v) 

    def __setattr__(self, name, value): 
     if name == '_value': super(Frozen, self).__setattr__(name, value) 
     else: raise Exception("Can't modify frozen object {0}".format(self._value)) 

def const(some_function):  
    def wrapper(fargs,*args,**kwargs): 
     for f in fargs: 
      f = Frozen(f) 
      pass 
     for a in args: 
      a = Frozen(a) 
      pass 
     for k in kwargs: 
      k = Frozen(k) 
      pass 
     some_function(fargs, *args, **kwargs)  
    return wrapper 

@const 
def demo_function(list_in): 
    list_out = copy.deepcopy(list_in) 
    list_in.append("howdy") 
    return list_out 

lisandra = [1, 2, 3, 4, 5] 

modified_lisandra = demo_function(lisandra) 

print(lisandra) 

Edit:

Je regrette l'aide d'une liste comme mon exemple. Je veux vraiment une solution générale qui rendrait les entrées d'une fonction immuables (const), quels que soient leurs types de données. Il est très facile de convertir une liste python en un tuple. Cependant, que se passe-t-il si l'entrée de la fonction est une instance d'une classe définie par l'utilisateur? Vous ne savez pas comment le convertir en tuple. Même si vous savez comment convertir l'objet en tuple, vous ne voulez pas écrire une solution différente pour chaque type de données dans votre projet. Nous voulons une solution unique qui va geler les valeurs des entrées d'une fonction, quel que soit le type de données de ces entrées.

+0

Utilisez un tuple? 'lisandra = (1, 2, 3, 4, 5)' – James

+0

Vous pouvez utiliser un tuple à la place. –

+0

Pourquoi voulez-vous que ce soit immuable? Qu'espérez-vous gagner? –

Répondre

0

Vous pouvez toujours essayer quelque chose comme ça ..

import copy 

def demo_function(list_in): 
    original = list_in[:] 
    list_out = copy.deepcopy(list_in) 
    list_in.append("howdy") 
    assert original == list_in 
    return list_out