2010-10-15 10 views
7

Est-il possible de déclarer des fonctions en python et de les définir plus tard ou dans un fichier séparé?Déclaration de fonction en python pour avoir un code lisible et propre?

J'ai un code comme:

class tata: 
    def method1(self): 
     def func1(): 
     # This local function will be only used in method1, so there is no use to 
     # define it outside. 
     # Some code for func1. 
     # Some code for method1. 

Le problème est que le code devient à lire en désordre et difficile. Donc, je me demande s'il est possible par exemple de déclarer func1 à l'intérieur de method1 et de le définir plus tard?

+0

Si la fonction func1() n'est réellement pertinente que pour method1(), et que la méthode interne devient un problème pour vous, c'est une indication qu'il devrait s'agir d'une classe distincte. –

Répondre

6

Bien sûr, pas de problème:

foo.py:

def func1(): 
    pass 

script.py:

import foo 
class tata: 
    def method1(self): 
     func1=foo.func1 
+0

Belle réflexion! Cependant, l'idée d'une fonction locale est de rendre cette fonction utilisable uniquement à l'intérieur de la portée interne. Alors, quel est le point de définir le nouveau 'func1' dans' method1'? Ce ne serait pas plus facile à faire: 'from foo import func1' et l'utiliser. – banx

+0

@banx: La réponse d'Alex Martelli ici (http: // stackoverflow.com/questions/1744258/is-importation-module-mieux-codage-style-que-de-module-importation-fonction) m'a persuadé d'éviter complètement «de foo importer func1». – unutbu

+0

@banx: Oui, mettre la définition de 'func1' dans' method1' la rend au moins semi-privée, même si je ne la mettrais pas devant un hacker bytecode entreprenant (http://stackoverflow.com/questions/3908335/python -function-local-name-binding-from-a-outer-scope/3913185 # 3913185) pour trouver un moyen de faire ce que vous pensez est privé non-si-privé. – unutbu

2

La définition interne crée un nom distinct dans la portée interne. Il ombrera tout ce que vous définissez plus tard avec le même nom. Si vous voulez définir la fonction plus tard, alors faites-le. Le nom ne sera vérifié que lorsqu'il sera réellement utilisé.

def foo(): 
    print 'foo' 
    bar() 

def bar(): 
    print 'bar' 

foo() 
3

Je pense que ce que vous voulez est d'importer la fonction dans method1 , par exemple

def method1(...): 
    from module_where_func1_is_defined import func1 
    # do stuff 
    something = func1(stuff, more_stuff) 
    # do more stuff 

Les modules Python sont essentiellement des fichiers; Tant que le fichier module_where_func1_is_defined.py est dans le même répertoire que votre script, method1 pourra l'importer.

Si vous voulez être en mesure de personnaliser la façon dont method1 œuvres, et aussi faire encore plus clair qu'il utilise func1, vous pouvez passer func1-method1 comme paramètre par défaut:

import other_module 

# various codes 

def method1(other_args, func=other_module.func1) 
    # do stuff 
    something = func(stuff, more_stuff) 
    # do more stuff 
2

Si func1 () a besoin de gérer tout ce qui est contenu dans la portée de method1(), il vaut mieux y laisser la définition de func1(). Vous devez avoir func1() recevoir des données pertinentes en tant que paramètres si elle est pas définie dans le cadre de method1()

+0

+1 Étant donné que les fonctions imbriquées accèdent directement aux noms de leur portée de conteneur, c'est un idiome important dans Python. Ses règles de portée actuelles sont très puissantes et bien pensées - voir [PEP 227 - Étalons statiquement imbriqués (ttp: //www.python.org/dev/peps/pep-0227/) introduit dans Python 2.1. Mettre des définitions dans un fichier séparé empêcherait actuellement cela à moins d'être travaillé d'une manière ou d'une autre. – martineau

0

Vous pouvez créer des méthodes après

 

class Something(object): 
    def test1(self): 
    pass 

def dummy(self): 
    print "ok", self 

Something.test1 = dummy 

Cependant, il est impossible d'avoir un anonyme fonction (bien, il y a des expressions lambda, mais vous ne pouvez pas avoir des déclarations là-bas), vous devez fournir un nom temporaire

vous pouvez utiliser les décorateurs afin de le rendre plus lisible:

 
def define(cls, name): 
    def decor(f): 
    setattr(cls, name, f) 
    return decor 


class Something(object): 
    def test1(self): 
    pass 

@define(Something, "test1") 
def dummy(self): 
    print "ok", self 

Ce code devrait être plus lisible. Il polluera toujours dummy mais l'initialisera avec null.