2013-06-27 10 views
7

OK, używam Python 2.7.3 i tu jest mój kod:Zmienne globalne w rekursji. 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)) 

Próbuję zmodyfikować zmienną count wewnątrz funkcji leng. Oto rzeczy, które próbowałem:

  1. Jeśli mogę umieścić zmienną liczbę poza funkcją lenRecur działa dobrze za pierwszym razem, ale gdy próbuję ponownie bez konieczności ponownego uruchamiania Pythona powłoki, hrabia (oczywiście) nie robi” t restart, więc ciągle dodaje.
  2. Jeśli zmienię linię count += 1 dla count = 1 to również działa, ale wynik jest (oczywiście) jeden.

Moim celem jest uzyskanie długości ciągu przy użyciu rekursji, ale nie wiem, jak śledzić liczbę liter. Szukałem informacji na temat zmiennych globalnych, ale nadal utknąłem. Nie wiem, czy jeszcze tego nie zrozumiałem, czy też mam problem z moim kodem.

Z góry dziękuję!

+0

nie widzi samej rekursji. – oleg

+0

Przepraszam, teraz jest dobrze! –

Odpowiedz

12

count w lenRecur jest nie globalna. Jest to zmienna zakresu.

Musisz użyć Pythona 3, aby móc wykonać tę pracę w ten sposób; szukasz w nonlocal statement dodany do Pythona 3.

W Pythonie 2, można obejść to ograniczenie przez stosując zmienny (takie jak listy) dla count zamiast:

def lenRecur(s): 

    count = [0] 

    # ... 

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

Teraz nie są dłuższe zmienianie samej nazwy; pozostaje niezmieniony, ciągle odnosi się do tej samej listy. Wszystko, co robisz, zmienia pierwszy element zawarty w na liście count.

Alternatywnym „pisownia” byłoby zrobić count atrybut funkcję:

def lenRecur(s): 

    # ... 

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

    leng.count = 0 

count Teraz już nie jest lokalnym lenRecur(); stał się atrybutem niezmiennej funkcji lenRecur().

W przypadku konkretnego problemu, w rzeczywistości można o tym myśleć. Wystarczy rekursja wykonać sumowanie:

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

Czy jest jakiś sposób to zrobić w Pythonie 2.7? –

+0

lub Możesz przekazać count jako parametr funkcji 'leng' – oleg

+0

Ok, który pracował dla mnie! Czy mogę zapytać, dlaczego lista działa, a nie normalna zmienna? –

0

zdefiniować go na zewnątrz wszystkie definicje funkcji, jeśli chcesz używać go jako zmienną globalną:

count = 0 
def lenRecur(s): 

lub zdefiniuj go jako atrybut funkcji:

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

Zostało to naprawione w py3.x, gdzie można użyć instrukcji nonlocal:

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

Jeśli to określę poza funkcją lenRecur to pierwsze stwierdzenie, które powiedziałem, że próbowałem. Dzięki i tak! –

+0

@CarlesMitjans Chyba przegapiłem ten szczegół, możesz zdefiniować go jako atrybut funkcji. –

+0

Nie martw się :) dziękuję za odpowiedź! –

0

Nie trzeba liczyć. Poniższa funkcja powinna działać.

 

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

Działa również! Dzięki!! –

4

myślę, że można przejść liczone jako drugi argument

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

    return leng(isChar(s), 0) 

to powinno działać lepiej niż wyciszanie obiektów z zakresu zewnętrznej, takich jak przy użyciu obiektów zmienny (list lub dict) lub funkcję sama dla małpa-łatanie przykład.

+0

Ouch! Nie myślałem o tym. Dzięki! –

+0

Wysłałem tę samą odpowiedź. Nie widziałem Twojego posta. Chyba spóźniam się jak zwykle :-) – thiruvenkadam

+2

Lepiej zagłosuj na moje rozwiązanie zamiast komentować;) – oleg

1

Trzeba uczynić zmienna liczyć zmienną działać jak

def lenRecur(s): 
    lenRecur.count = 0 

Jednak widzę kilka problemów z kodem.

1) Jeśli próbujesz znaleźć liczbę alfabetów w sznurku przez rekursji, ten zrobi:

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) 

Ale nadal wolałbym posiadające jedną funkcję, aby wykonać zadanie, jak tam w ogóle nie będzie to żadna metoda.

2) Jeśli twoim celem jest po prostu znaleźć liczbę alfabetów w ciąg, wolałbym listowych

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

Jeśli jest to coś innego niż cel nauki, proponujemy, aby uniknąć rekursji. Ponieważ rozwiązanie nie może być używane dla większych ciągów (powiedzmy, znajdowanie liczby alfabetu od zawartości pliku). Możesz trafić w RunTimeError przekroczonej maksymalnej głębokości rekursji.

Mimo że można obejść to poprzez ustawienie głębokości rekurencji za pomocą funkcji setrecursionlimit, sugeruję, aby przejść na inne proste sposoby. Więcej informacji na temat ustawiania recursionlimit here.