2010-10-15 4 views
7

È possibile dichiarare funzioni in python e definirle successivamente o in un file separato?Dichiarazione di funzione in python per avere un codice leggibile e pulito?

ho qualche codice come:

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. 

Il problema è che il codice diventa disordinato e difficile da leggere. Quindi mi chiedo se è possibile ad esempio dichiarare func1 all'interno di method1 e definirlo in seguito?

+0

Se func1() è davvero rilevante solo per method1(), e il metodo interno diventa un problema per te, è un'indicazione che dovrebbe essere davvero una classe separata. –

risposta

6

Certo, nessun problema:

foo.py:

def func1(): 
    pass 

script.py:

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

Bel pensiero! Tuttavia, l'idea di una funzione locale è di rendere questa funzione utilizzabile solo all'interno dello scope interno. Quindi, qual è il punto di definizione del nuovo 'func1' all'interno di' method1'? Non sarebbe più facile da fare: 'da foo import func1' e usarlo. – banx

+0

@banx: la risposta di Alex Martelli qui (http: // stackoverflow.it/questions/1744258/is-import-module-better-coding-style-than-from-module-import-function) mi ha convinto ad evitare 'from foo import func1' interamente. – unutbu

+0

@banx: Sì, mettere la definizione di 'func1' dentro' method1' lo rende almeno semi-privato, anche se non lo metterei al di là di un intraprendente hacker bytecode (http://stackoverflow.com/questions/3908335/python -function-local-name-binding-from-an-outer-scope/3913185 # 3913185) per trovare un modo per rendere privato-non-privato ciò che si pensa sia privato. – unutbu

2

La definizione interna crea un nome separato nell'ambito interno. Osmerà qualsiasi cosa tu definisca in seguito con lo stesso nome. Se si desidera definire la funzione in un secondo momento, è sufficiente farlo. Il nome verrà controllato solo quando viene effettivamente utilizzato.

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

def bar(): 
    print 'bar' 

foo() 
3

Penso che ciò che si desidera è di importare la funzione all'interno method1 , per esempio

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

I moduli Python sono fondamentalmente solo file; finché il file module_where_func1_is_defined.py si trova nella stessa directory del tuo script, method1 sarà in grado di importarlo.

Se si vuole essere in grado di personalizzare il modo in cui method1 opere, e anche rendere ancora più chiaro che usa func1, è possibile passare func1-method1 come parametro predefinito:

import other_module 

# various codes 

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

Se func1 () ha bisogno di gestire qualsiasi cosa contenuta nell'ambito di method1(), è meglio lasciare la definizione di func1() lì. Dovrete avere FUNC1() riceve dati pertinenti come parametri, se non è definito nell'ambito di method1()

+0

+1 Perché avere funzioni nidificate che accedono direttamente ai nomi dal loro ambito di contenimento è un idioma importante in Python. Le attuali regole di scoping sono molto potenti e ben congegnate - si veda [PEP 227 - Static Nested Scopes (ttp: //www.python.org/dev/peps/pep-0227/) introdotto in Python 2.1. Mettere le definizioni in un file separato potrebbe impedirlo al momento, a meno che non funzioni in qualche modo. – martineau

0

È possibile creare metodi dopo

 

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

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

Something.test1 = dummy 

Tuttavia non è possibile avere un anonimo la funzione (beh, ci sono le espressioni lambda, ma non si può avere dichiarazioni lì), quindi bisogna fornire un nome temporaneo

si potrebbe desiderare di utilizzare decoratori al fine di renderlo più leggibile:

 
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 

Questo codice dovrebbe essere più leggibile. Continuerà a inquinare il dummy ma lo inizializzerà con null.