2017-09-06 5 views
1

En Python, il est possible d'accéder à des fonctions variables module comme suit:Est-il considéré comme une mauvaise pratique d'accéder aux variables du module à partir de la fonction?

def pow(a): 
    return a**b 

a = 3 
b = 2 
print(pow(a)) 

Est-ce considéré comme une mauvaise pratique?

L'alternative évidente serait de transmettre explicitement tous les arguments aux fonctions:

def pow(a, b): 
    return a**b 

a = 3 
b = 2 
print(pow(a, b)) 

J'utilise la première forme comme un moyen de limiter le nombre de paramètres passés à une fonction, et je me demandais si ce est considéré comme une mauvaise pratique.

+3

oui et non. ce n'est pas un style de codage très propre mais en même temps, * si vous savez ce que vous faites *, et vous avez une raison à cela, c'est correct. Maintenant, spécifiquement pour l'exemple que vous avez posté ci-dessus, je ne vois pas de raison. –

+2

Je ne vois aucun problème ici. Il est préférable de rendre les fonctions autonomes, mais ce n'est pas un crime d'utiliser des globals dans les fonctions, les globals sont des globals. La réponse dépend de votre application. Je ne peux même pas dire si manger de la glace dans une journée froide est une mauvaise habitude. – direprobs

+0

A la fin j'ai utilisé la deuxième alternative. Pour limiter le nombre de paramètres, j'ai créé une classe les encapsulant.Cependant, j'ai des constantes de module globales définies en haut du module pour toutes les fonctions (je n'y vois aucun problème) –

Répondre

1

Il est préférable de passer explicitement la variable à la fonction. L'intention est plus claire de cette façon, tout comme le but de la fonction. Considérez ce qui suit:

my_list = [1, 2, 3] 
min_len = 5 

def check_length(my_list): 
    return len(my_list) < min_len 

check_length(my_list) 

À première vue, je vois que check_length est appelée, mais quelle longueur est-il vérifier contre? Si je ne le savais pas, je devrais le chercher. C'est un problème qui ne se développe qu'avec des scripts et des fonctions plus importants.

1

Cela dépend vraiment de votre contexte d'utilisation, depuis:

  1. La seule façon d'accéder à des modules importés est de référencer leur espace de noms dans le cadre du module:

:

import foo 
import bar_var from bar as bvar 

def myfun(a): 
    return foo.foo_func(a) 
    # foo is in module namespace, nobody adds it to the caller's signature 

def myfun2(b): 
    myfun(b) 

>>> myfun2(bvar) # returns foo.foo_func(bvar) 
  1. L'utilisation des règles d'étendue lexicale python est la seule façon d'implémenter des fermetures:

:

def outerfun(a): 

    def innerfun(): 
     return a 

    return innerfun 

>>> inner_alias = outerfun("foo") 
>>> inner_alias() 
"foo" 

Suivez donc les meilleures pratiques pour: le code rendant facile à lire et gérer les variables/namespaces mondiales, se rappelant expressément que mutables datastructures seront modifiés indépendamment du fait qu'ils ont été adoptées dans la signature ou non :

:

L = [] 

def foo(alist): 
    alist.append(1) 
    return alist 

def foo2(): 
    L.append(1) 
    return L 

>>> foo(L) 
[1] 
>>> L 
[1] #!!! (lists are mutable and python passes by assignment) 
>>> foo2() 
[1, 1] 
>>> L 
[1, 1] 

PS En OOP avec Python, les méthodes d'instance sont explicitement définies par l'instance comme premier argument (mais automatiquement appelé implicitement cet argument), exposant l'espace de noms de classe à la méthode:

:

class myClass(object): 
    def __init__(self): # the first argument must be the instance 
     # __init__ is the constructor which we are overriding here 
     self.inst_var1 = 1 
     # initialize an instance var 

    def add(self, i): # the first argument must be the instance 
     if i <= 0: 
      raise ValueError("i must be a positive number!") 
      # But ValueError is a module global, because Exceptions are in global namespace 
     return self.inst_var1 + i 

>>> myclass_inst = myClass() 
>>> myclass_inst.inst_var1 
1 
>>> myclass_inst.add(1) 
# python automatically binds first argument to `myclass_inst`, 
# as if myclass_inst.add = functools.partial(myclass_inst.add, myclass_inst) 
2