Khai báo hàm ở cuối tệp bằng Python


94

Có thể gọi một hàm mà không cần xác định đầy đủ trước không? Khi thử điều này, tôi gặp lỗi: " function_name không được xác định". Tôi đến từ nền tảng C ++ nên vấn đề này khiến tôi khó chịu.

Khai báo hàm trước khi hoạt động:

def Kerma():
        return "energy / mass"    

print Kerma()

Tuy nhiên, cố gắng gọi hàm mà không xác định trước nó sẽ gây ra rắc rối:

print Kerma()

def Kerma():
    return "energy / mass"

Trong C ++, bạn có thể khai báo một hàm sau lời gọi khi bạn đặt tiêu đề của nó trước nó.

Am i thiếu cái gì ở đây?


5
Trong Python không có "khai báo". Có định nghĩa (phải đầy đủ) hoặc không có gì.
S.Lott

2
Bạn nói, "nó mang lại rắc rối". bạn có thể giải thích về điều đó không?
Martin Del Vecchio


Trong trường hợp có ai đó đang thắc mắc:Kerma is an acronym for "kinetic energy released per unit mass"
anon

1
Tôi biết điều này rất cũ, nhưng tại sao không ai đề xuất đặt các chức năng trong một .pytệp riêng biệt và nhập nó? Có một số hậu quả ngoài ý muốn?
Kyle

Câu trả lời:


145

Một cách khá thành ngữ trong Python là viết:

def main():
    print Kerma()

def Kerma():
    return "energy / mass"    

if __name__ == '__main__':
    main()

Điều này cho phép bạn viết mã theo thứ tự bạn thích miễn là bạn tiếp tục gọi hàm mainở cuối.


4
@Muhammad: trong khi đây là một cách tiếp cận khả thi, nó chắc chắn không phải là thành ngữ trong Python. Hoàn toàn ngược lại, bạn sẽ nhận thấy hầu hết các mainchức năng thường được đặt ở cuối.
Eli Bendersky

14
@Eli Bendersky: Tôi muốn gửi rằng công if __name__ == '__main__':tắc là phần thành ngữ phổ biến.
S.Lott

2
@Eli: phần thành ngữ là mệnh đề if ở cuối: không có mã nào ở cấp cao nhất của mô-đun, sau đó ở cuối gọi một hàm chính nếu mô-đun là chính .
Ned Batchelder

1
@Eli: Phần thành ngữ là if ... __main__':. Tôi đã không nói rằng mainnên đặt phía trên phần còn lại của mã. Tôi đã nói phần quan trọng là gọi _\_main__ở cuối, và khi đó bạn đặt định nghĩa của nó ở đâu không quan trọng.
Muhammad Alkarouri

2
Với if name == ' main ': chuyển đổi nó trở nên không liên quan đến cách bạn sắp xếp các chức năng của mình. Đó là điều đúng đắn (TM) phải làm.
MKesper

18

Khi một mô-đun Python (tệp .py) được chạy, các câu lệnh cấp cao nhất trong đó được thực thi theo thứ tự xuất hiện, từ trên xuống dưới (đầu đến cuối). Điều này có nghĩa là bạn không thể tham chiếu một cái gì đó cho đến khi bạn đã xác định nó. Ví dụ sau đây sẽ tạo ra lỗi được hiển thị:

c = a + b  # -> NameError: name 'a' is not defined
a = 13
b = 17

Không giống như với nhiều ngôn ngữ khác, defvà các classcâu lệnh có thể thực thi bằng Python - không chỉ là khai báo - vì vậy bạn không thể tham chiếu ahoặc bcho đến khi điều đó xảy ra và chúng được xác định. Đây là lý do tại sao ví dụ đầu tiên của bạn gặp sự cố — bạn đang tham chiếu đến Kerma()hàm trước khi defcâu lệnh của nó được thực thi và nội dung đã được xử lý và đối tượng hàm kết quả được liên kết với tên của hàm, vì vậy nó không được định nghĩa tại thời điểm đó trong tập lệnh.

Các chương trình bằng ngôn ngữ như C ++ thường được xử lý trước trước khi chạy và trong giai đoạn biên dịch này, toàn bộ chương trình và bất kỳ #includetệp nào nó đề cập đến đều được đọc và xử lý cùng một lúc. Không giống như Python, ngôn ngữ này có các câu lệnh khai báo cho phép tên và trình tự gọi của các hàm (hoặc kiểu tĩnh của biến) được khai báo (nhưng không được định nghĩa), trước khi sử dụng để khi trình biên dịch gặp tên của chúng, nó có đủ thông tin để kiểm tra việc sử dụng, chủ yếu đòi hỏi kiểm tra kiểu và chuyển đổi kiểu, không điều nào trong số đó yêu cầu nội dung thực tế hoặc nội dung mã của chúng phải được xác định.


Không phải là một ngôn ngữ động không thể làm được điều đó. Perl là một ngôn ngữ động và bạn có thể gọi một hàm trước khi định nghĩa nó. Đó là bởi vì nó có một giai đoạn biên dịch và một giai đoạn thực thi (mặc dù kỳ lạ, nhưng hữu ích, bạn có thể sắp xếp để thực thi mã trong giai đoạn biên dịch). Đây hoạt động: doit(); sub doit { print("I'm doing it!\n"); }
John Deighan

9

Điều này là không thể trong Python, nhưng khá thẳng thắn rằng bạn sẽ sớm thấy mình không cần nó chút nào. Cách Pythonic để viết mã là chia chương trình của bạn thành các mô-đun xác định các lớp và chức năng, và một "mô-đun chính" duy nhất nhập tất cả các mô-đun khác và chạy.

Đối với các tập lệnh đơn giản, hãy quen với việc đặt "phần thực thi" ở cuối, hoặc tốt hơn, hãy học cách sử dụng một trình bao tương tác Python.


1

Python là một ngôn ngữ động và trình thông dịch luôn lấy trạng thái của các biến (hàm, ...) như hiện tại khi gọi chúng. Bạn thậm chí có thể xác định lại các chức năng trong một số if-block và gọi chúng mỗi lần theo cách khác nhau. Đó là lý do tại sao bạn phải xác định chúng trước khi gọi chúng.


1

Nếu bạn sẵn sàng giống như C ++ và sử dụng mọi thứ bên trong một hàm. bạn có thể gọi hàm đầu tiên từ cuối tệp, như sau:

def main():
    print("I'm in main")
    #calling a although it is in the bottom
    a()

def b():
   print("I'm in b")

def a():
   print("I'm in a")
   b()

main()

Bằng cách đó, python trước tiên 'đọc' toàn bộ tệp và chỉ sau đó bắt đầu thực thi

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.