2012-05-15 3 views
3

je la méthode suivante:Valeur par défaut pour argument optionnel en Python:

def get_data(replace_nan=False): 
    if replace_nan is not False 
     data[numpy.isnan(data)] = replace_nan 
     return data 
    else: 
     return data[~numpy.isnan(data)] 

Donc, si replace_nan est faux, nous revenons une série de données, mais supprimer NaN s, et si elle est autre chose, nous remplaçons NaN s avec l'argument. Le problème est, je peux vouloir remplacer NaN avec False. Ou toute autre chose, pour ça. Quelle est la manière la plus pythonique de le faire? Ce:

def get_data(**kwargs): 
    if "replace_nan" in kwargs: 
     ... 

fonctionne, mais est sémantiquement laid (parce que nous sommes intéressés vraiment juste un argument de mot-clé, replace_nan) Toute suggestion comment gérer ce cas?

Répondre

4

Habituellement, les gens utilisent None comme valeur par défaut, puis vérifient is not None.

Si vous devez autoriser None, aussi, utiliser un objet factice:

__default = object() 
def get_data(replace_nan=__default): 
    if replace_nan is __default: 
     ... 
+0

J'ai déjà utilisé 'False' car' None' est un remplacement fréquent des valeurs manquantes. Mais l'objet par défaut fictif est soigné, merci! –

2

numpy évalue tableau Faux l'intérieur à 0:

>>>np.array([False,True,2,3]) 
    array([0, 1, 2, 3]) 

Donc, cela pourrait probablement pas ce que vous voulez arriver .

def get_data(replace_nan=False): 
     if replace_nan: 
      return np.where(np.isnan(data),replace_nan,data) 
     else: 
      return data[~numpy.isnan(data)] 

La fonction numpy.where crée un tableau avec les index où vos entrées sont NaN. Là, il remplace les entrées avec replace_nan, partout ailleurs il conserve les entrées.

De l'manual page:

numpy.where(condition[, x, y]) 
Return elements, either from x or y, depending on condition. 
1

Je voulais mettre cela comme commentaire ci-dessous la réponse de ThiefMaster mais pas de formatage dans les commentaires autorisés, alors ...:

Si vous êtes préoccupé par encombrer votre espace de noms que vous peut-avec quelques astuces- del la variable après avoir défini la fonction.

__default = object() 
def get_data(replace_nan=__default, __default=__default): 
    if replace_nan is __default: 
    ... 
del __default 

Ou:

__default = object() 
def get_data(replace_nan=__default): 
    if replace_nan is get_data.default_replace_nan: 
    ... 
get_data.default_replace_nan = __default 
del __default 
+0

Intéressant! Cependant, j'ai toujours pensé que '__...' était destiné à être encombré de toute façon ;-) –

+0

Traditionnellement, __ était réservé aux éléments internes au compilateur C et était donc un nono que le générateur d'applications utilisait. En Python, les choses sont un peu différentes. Quoi qu'il en soit: l'encombrement est un problème. Vous ne pouvez pas utiliser le nom '__default' pour la prochaine situation dans laquelle ce modèle pourrait être utile parce que vous écraseriez le' __default' de la première utilisation (et cassez le code dans le processus). L'encombrement devrait donc être évité, même si «__» pourrait rendre l'encombrement évident. – Alfe

1

Une autre façon d'éviter l'encombrement de l'approche de ThiefMaster est la suivante:

def get_data(replace_nan=object()): 
    if replace_nan is get_data.func_defaults[0]: 
    ... 

Mais il utilise python interna qui pourrait ne pas être aussi portable (pypy/stackles/prochaine version/...).

+0

Et vous pouvez même remplacer le '0' dans le code ci-dessus par' get_data.func_code.co_varnames.index ('replace_nan') 'pour être sûr contre les modifications ultérieures de la signature de get_data(). Mais maintenant, nous exagérons le problème, je suppose. – Alfe

Questions connexes