2012-07-06 39 views
20

Tôi vừa bắt đầu học python (v3.2.3) và đã gặp phải một vấn đề kỳ lạ về return trong hàm này:Return trong Function Recursive

def test(x): 
    if x > 9 : 
     test(x - 10) 
    else: 
     print('real value',x) 
     return x 

x = int(input()) 
y = test(x) 
print('this should be real value',y) 

Khi tôi chạy nó, tôi nhận được:

45 
real value 5 
this should be real value None 

Nhưng tôi mong đợi:

45 
real value 5 
this should be real value 5 

tôi đã cố gắng thêm return x ngoài if và tôi nhận giá trị đầu vào mặc định. Bất cứ ai có thể vui lòng giải thích cách return hoạt động?

+3

Nó chính xác giống như cuộc gọi không đệ quy: nếu bạn muốn truyền giá trị trả về từ hàm bạn gọi, bạn phải tự làm điều đó, với từ khóa 'return'. Gọi một hàm tạo ra giá trị trả về của nó, nhưng nó tùy thuộc vào bạn để làm điều gì đó với giá trị trả về đó, cho dù hàm được gọi là đệ quy hay không. –

Trả lời

13

Trả lại được thụt lề để nó chỉ thực thi trong nhánh khác. Nếu nhánh đầu tiên được lấy, hàm sẽ trả về không có gì.

Bạn cần phải thay đổi điều này để

return test(x-10) 
+0

do đó, điều này có nghĩa rằng tôi cần phải có trở lại ngay cả trên sai nếu không điều kiện? –

+1

@AlexKey: Có. Vì 'y' được gán giá trị từ lần gọi hàm đầu tiên. Đây không phải là điều duy nhất đối với Python. Phần duy nhất duy nhất đối với Python là hàm trả về 'None' khi không có câu lệnh trả về. –

4

Bạn quên trả về giá trị khi x > 9. Không có giá trị trả về, hàm sẽ "trả về" None.

+0

vì vậy trong tóm tắt tôi cần phải đặt trở lại trên cả hai điều kiện là nó? –

+0

@AlexKey: Trong đoạn mã trên, có, bạn sẽ trả về giá trị của việc đánh giá 'test (x - 10)' – nhahtdh

34

Bạn gọi test(45). Điều này kiểm tra xem 45 > 9 có đúng không, do đó, nó gọi test(35) (45 - 10), mà không trả về kết quả của nó. Điều tương tự cũng xảy ra với test(25)test(15), cho đến khi cuối cùng test(5) được gọi.

Bản in này 'giá trị thực 5' và sau đó trả về 5. Nhưng trả lại kết quả từ hàm luôn là trả về cho người gọi trực tiếp của hàm này. Nó không nhảy ngay lập tức thông qua một số cuộc gọi; sau khi tất cả, người gọi có thể muốn làm điều gì đó với kết quả trả về trước khi trả lại một cái gì đó cho số đó là số gọi. Trong trường hợp này, mặc dù chỉ có test(5) trả về bất kỳ thứ gì; tất cả những người khác gọi số test(x - 10), chờ điều đó để trả lại, bỏ qua bất kỳ điều gì nó trả về, và sau đó (ngầm) trả về None. Kể từ khi yêu cầu ngoài cùng test(45) là một trong những trường hợp này, những gì bạn nhận được là None.

Dưới đây là một nỗ lực tại một hình dung về những gì sẽ xảy ra:

test(45): 
| test(35): 
| | test(25): 
| | | test(15): 
| | | | test(5): 
| | | | | print('real value',5) 
| | | | | return 5 to test(15) 
| | | | return None to test(25) 
| | | return None to test(35) 
| | return None to test(45) 
| return None 

Bạn không gọi test(5) trong phiên dịch, test(5) được gọi từ bên trong một lời gọi hàm. Vì vậy, sự trở lại từ test(5) chuyển đến mà gọi hàm. Thực tế là đây là một chức năng tự gọi là hoàn toàn không liên quan. Bạn sẽ nhận được chính xác kết quả tương tự nếu mã của bạn trông như thế này:

def test45(x): 
    if x > 9 : 
     test35(x - 10) 
    else: 
     print('real value',x) 
     return x 

def test35(x): 
    if x > 9 : 
     test25(x - 10) 
    else: 
     print('real value',x) 
     return x 

def test25(x): 
    if x > 9 : 
     test15(x - 10) 
    else: 
     print('real value',x) 
     return x 

def test15(x): 
    if x > 9 : 
     test5(x - 10) 
    else: 
     print('real value',x) 
     return x 

def test5(x): 
    if x > 9 : 
     print 'No more tests :(' 
    else: 
     print('real value',x) 
     return x 

Thử nghiệm (x) chức năng bạn gọi với 'x = 45' là giống như gọi test45(45). Tôi hy vọng bạn có thể thấy lý do tại sao rõ ràng là None phải được trả lại khi đệ quy không phải là tham gia. Vâng, khi đệ quy được tham gia, không có gì thay đổi. Câu lệnh return không biết và cũng không quan tâm liệu nó có trả về từ một hàm được gọi đệ quy hay không, nó hoạt động chính xác theo cùng một cách trong cả hai trường hợp.

Trong thực tế, đệ quy không phải là bất cứ điều gì "đặc biệt"; nó hoạt động giống hệt như các cuộc gọi hàm bình thường. Bạn nhận được thông tin từ thứ gọi bạn qua các đối số và bạn trả lại thông tin về thứ gọi là bạn bằng cách quay lại. Nếu bạn không trả lại thứ gì đó (có lẽ chỉ trong một cánh tay của if), thì None sẽ được trả lại cho người gọi của bạn, bất kể bạn gọi bất kỳ chức năng nào khác trong nhánh đó, bất kể chức năng đó có thể trở lại như thế nào nếu bạn gọi một cái gì đó, và bất kể cho dù chức năng bạn gọi xảy ra là chức năng tương tự bạn đang ở bên trong.