2013-06-27 11 views
7

OK, sto usando Python 2.7.3 e qui è il mio codice:Variabili globali in ricorsione. Python

def lenRecur(s): 

    count = 0 

    def isChar(c): 
     c = c.lower() 
     ans='' 
     for s in c: 
      if s in 'abcdefghijklmnopqrstuvwxyz': 
       ans += s 
     return ans 

    def leng(s): 
     global count 
     if len(s)==0: 
      return count 
     else: 
      count += 1 
      return leng(s[1:]) 

    return leng(isChar(s)) 

sto cercando di modificare la variabile count all'interno della funzione leng. Qui ci sono le cose che ho provato:

  1. Se metto il conteggio variabile di fuori della funzione lenRecur funziona benissimo la prima volta, ma se provo ancora una volta senza riavviare shell Python, il conteggio (ovviamente) doesn' t ricomincia, quindi continua ad aggiungere.
  2. Se cambio la linea count += 1 per count = 1, funziona anche, ma l'output è (ovviamente) uno.

Quindi, il mio obiettivo è quello di ottenere la lunghezza della stringa utilizzando la ricorsione, ma non so come tenere traccia del numero di lettere. Ho cercato informazioni sulle variabili globali, ma sono ancora bloccato. Non so se non l'ho ancora capito, o se ho un problema nel mio codice.

Grazie in anticipo!

+0

non può vedere la ricorsione stessa. – oleg

+0

Siamo spiacenti, ora è ok! –

risposta

12

count in lenRecur è non un globale. È una variabile con scope.

Avrete bisogno di usare Python 3 prima di poter fare quel lavoro in questo modo; si sta cercando per il nonlocal statement aggiunto a Python 3.

In Python 2, è possibile aggirare questa limitazione utilizzando un mutabile (ad esempio una lista) count invece:

def lenRecur(s): 

    count = [0] 

    # ... 

    def leng(s): 
     if len(s)==0: 
      return count[0] 
     else: 
      count[0] += 1 
      return lenIter(s[1:]) 

Ora non sei modificare più a lungo il nome di count; rimane invariato, continua a riferirsi alla stessa lista. Tutto quello che stai facendo è modificare il primo elemento nella lista nell'elenco count.

Un 'spelling' alternativa sarebbe quella di fare un attributo count funzione:

def lenRecur(s): 

    # ... 

    def leng(s): 
     if len(s)==0: 
      return leng.count 
     else: 
      leng.count += 1 
      return lenIter(s[1:]) 

    leng.count = 0 

Ora count non è più locale per lenRecur(); è diventato invece un attributo sulla funzione invariata lenRecur().

Per il tuo problema specifico, stai davvero pensando troppo alle cose. Basta avere la ricorsione fare la somma:

def lenRecur(s): 
    def characters_only(s): 
     return ''.join([c for c in s if c.isalpha()]) 

    def len_recursive(s): 
     if not s: 
      return 0 
     return 1 + len_recursive(s[1:]) 

    return len_recursive(characters_only(s)) 

Demo:

>>> def lenRecur(s): 
...  def characters_only(s): 
...   return ''.join([c for c in s if c.isalpha()]) 
...  def len_recursive(s): 
...   if not s: 
...    return 0 
...   return 1 + len_recursive(s[1:]) 
...  return len_recursive(characters_only(s)) 
... 
>>> lenRecur('The Quick Brown Fox') 
16 
+0

C'è un modo per farlo in Python 2.7? –

+0

oppure È possibile passare il conteggio come parametro alla funzione 'leng' – oleg

+0

Ok che ha funzionato per me! Posso chiederti perché ha funzionato una lista e non una variabile normale? –

0

definirlo fuori tutte le definizioni di funzioni, se si desidera utilizzarlo come una variabile globale:

count = 0 
def lenRecur(s): 

o definirlo come attributo di funzione:

def lenRecur(s): 
    lenRecur.count = 0 
    def isChar(c): 

Questo problema è stato risolto in py3.x dove è possibile utilizzare l'istruzione nonlocal:

def leng(s): 
    nonlocal count 
    if len(s)==0: 
+0

Se lo difendo fuori dalla funzione lenRecur è la prima affermazione che ho detto che ho provato. Grazie comunque! –

+0

@CarlesMitjans Suppongo di aver perso quel dettaglio, puoi definirlo come un attributo di funzione. –

+0

Non preoccuparti :) grazie per la risposta! –

0

Non hai bisogno di conteggio. La funzione qui sotto dovrebbe funzionare.

 

    def leng(s): 
     if not s: 
      return 0 
     return 1 + leng(s[1:]) 
 
+0

Anche lavorato! Grazie!! –

4

Penso che si possa passare contano come secondo argomento

def anything(s): 
    def leng(s, count): 
     if not s: 
      return count 
     return leng(s[1:], count + 1) 

    return leng(isChar(s), 0) 

questo dovrebbe funzionare meglio di muting oggetti dal campo di applicazione esterna come l'utilizzo di oggetti mutabili (list o dict) o funzione stessa scimmia-patching per esempio.

+0

Ouch! Non ci ho pensato. Grazie! –

+0

Ho postato la stessa risposta. Non ho visto il tuo post lì. Immagino di essere in ritardo come al solito :-) – thiruvenkadam

+2

Faresti meglio a votare per la mia soluzione invece di commentarla;) – oleg

1

Hai bisogno di fare il conteggio alla variabile una variabile funzione come

def lenRecur(s): 
    lenRecur.count = 0 

Tuttavia, vedo qualche problema con il codice.

1) Se si sta cercando di trovare il numero di alfabeti in una stringa attraverso ricorsione, questo farà:

def lenRecur(s): 
    def leng(s, count = 0): 
      if not s: 
        return count 
      else: 
        count += int(s[0].isalpha()) 
        return leng(s[1:], count) 
    return leng(s) 

Ma ancora io preferirei avere una sola funzione di fare il compito, come se non ci non sarà affatto un metodo leng.

2) Se il vostro obiettivo è solo quello di trovare il numero di alfabeti in una stringa, preferirei di lista

def alphalen(s): 
    return sum([1 for ch in s if ch.isalpha()]) 

Se questo è qualcosa di diverso da imparare scopo, vi consiglio di evitare la ricorsione. Perché, la soluzione non può essere utilizzata per stringhe più grandi (diciamo, trovando il conteggio alfabetico dal contenuto di un file). È possibile che si verifichi l'errore RunTimeError di Maximum Recursion Depth Exceeded.

Anche se è possibile aggirare questo problema impostando la profondità di ricorsione attraverso la funzione setrecursionlimit, ti suggerisco di andare per altri semplici modi. Maggiori informazioni sull'impostazione del limite di ricorrenza here.