Python 為什麼沒有 main 函數?為什麼我不推薦寫 main 函數?

来源:https://www.cnblogs.com/pythonista/archive/2020/06/03/13040342.html
-Advertisement-
Play Games

毫無疑問 Python 中沒有所謂的 main 入口函數,但是網上經常看到一些文章提“Python 的 main 函數”、“建議寫 main 函數”…… 有些人是知情的,他的意圖可能是模仿那些正宗的 main 函數,但還有不少人明顯是被誤導了(或自己誤解了),就寫出來很累贅的代碼。 本期“Pytho ...


毫無疑問 Python 中沒有所謂的 main 入口函數,但是網上經常看到一些文章提“Python 的 main 函數”、“建議寫 main 函數”……

有些人是知情的,他的意圖可能是模仿那些正宗的 main 函數,但還有不少人明顯是被誤導了(或自己誤解了),就寫出來很累贅的代碼。

本期“Python 為什麼”欄目來聊聊 Python 為什麼沒有 main 函數?

在開始正題之前,先要來回答這兩個問題:所謂的 “main 函數”是指什麼?為什麼有些編程語言需要強制寫一個 main 函數?

某些編程語言以 main 函數作為程式的執行入口,例如 C/C++、C#、 Java、Go 和 Rust 等,它們具有特定的含義:

  • main 函數名是強制的,也就是要求必須有一個 main 函數
  • main 函數最多只能有一個,也就是說程式的入口是唯一的
  • 語法格式有一定的要求,具有相對固定的模板

為什麼要強制一個 main 入口函數呢?

這些語言是編譯型語言,需要把代碼編譯成可執行的二進位文件,為了讓操作系統/啟動器找到程式的起點,所以要約定這一個函數。簡單地說,就是在一大堆代碼里,需要定義一個顯著的可用於執行的開頭。

不難看出,main 函數是那些語言中重要而不可缺的有機組成部分。

然而,我們再來看看 Python,情況就大不相同了。

  • Python 是解釋型語言,即腳本語言,運行過程是從上往下,逐行解析運行,也就是說它的起點是可知的
  • 每個 .py 文件就是一個可執行文件,都可作為整個程式的入口文件,也就是說程式的入口是靈活可變的,沒有必須遵守的約定
  • 有時候運行 Python 項目,並沒有指定入口文件(命令行中較常見,例如"python -m http.server 8000"), 那可能是存在 __main__.py 文件,它所在的包被當成一個“文件”來執行了

歸結起來,意思是說 Python 這種腳本語言跟編譯型語言不同,它不管是在單個模塊層面(即一個 .py 文件),還是在由多個模塊組成的包層面,都可選擇靈活的執行方式,不像其它語言缺了約定好的入口就沒法執行。

也就是說,Python 沒有必要在語法層面規定程式員必須定義出一個統一的入口(不管是函數還是類還是什麼東西)。

有些同學可能會有疑惑,因為他們經常看到或者自己寫出下麵這樣的代碼:

# main 里是某些主體代碼
def main():
    …… 
 
if __name__ == '__main__':
    main()

難道這不就是 Python 的 main 函數麽?相信有不少同學會這麼想!

非也!非也!

除了函數名是“main”以外,它跟我們前面介紹的正統的 main 函數沒有半毛錢關係,既沒有強制性,也沒有必然決定程式執行順序的作用。缺少它,也不會導致什麼語法問題。

之所以有些知情人要命名出一個”main“函數,其實是想強調它的”主要“地位,想要人為地安排它作為第一個執行的函數。他們可能認為這樣命名的函數,比較容易記憶。

之所以有些知情人要寫if __name__ == '__main__' ,可能想表明 main() 只有在當前腳本被直接執行時才運行,不希望被導入其它模塊時運行。

對於這些“知情人”,他們有一定的道理。

但是,我個人並不推薦這種寫法,甚至有時候會非常反感!

最明顯的例子:明明只有幾十行代碼,或者僅有一個腳本文件,實現一個簡單的功能(一小段爬蟲、用 turtle 畫張圖等等),但是它們都按前面的樣式寫了。

我每次看到這種不假思索的累贅代碼,就覺得難受。為什麼要寫那行 if 語句呢?可能的話,應該拆分 main 函數,甚至不必封裝成一個函數啊!

我個人總結出以下的經驗:

  • 打破慣性思維,寫出地道的代碼。main 入口函數是某些語言特有的,不該在 Python 中“照貓畫虎”,應該瞭解腳本語言的特點,寫出簡潔優雅的風格
  • 使用 main.py 而非 main()。因為 Python 的程式執行單位其實是腳本文件,而非某個函數或者類,所以建議把入口文件命名為 main.py,內部的函數按需求而定
  • 可以的話,使用__main__.py 作為入口文件。這個文件結合命令行的“-m”參數使用,非常好用。推薦閱讀:Python 中 -m 的典型用法、原理解析與發展演變
  • 不推薦寫if __name__ == '__main__' 。首先,如果只有一個文件的話,因為不存在導出的可能,不建議寫。其次,存在多文件時,入口文件(main.py)中極不推薦寫這一句,此文件的代碼邏輯應該精煉,理論上其內容不該被導出到其它模塊使用,因為它是起點!最後,多文件的非入口文件也不建議寫,因為在非入口文件中寫這個判斷,最大的作用就是寫一些測試代碼,但是測試代碼應該分離出來,寫到專門的目錄或文件中。

小結:本文首先解釋了什麼是 main 入口函數,以及為什麼某些語言會強制要求寫 main 函數;接著,解釋了為什麼 Python 不需要寫 main 函數;最後則是針對某些人存在的慣性誤區,分享了我個人的四點編程經驗。

本文屬於“Python為什麼”系列文章(Python貓出品),該系列主要關註 Python 的語法、設計和發展等話題,以一個個“為什麼”式的問題為切入點,試著展現 Python 的迷人魅力。部分話題會推出視頻版,請在 B 站收看,觀看地址:視頻地址

公眾號【Python貓】, 本號連載優質的系列文章,有Python為什麼系列、喵星哲學貓系列、Python進階系列、好書推薦系列、技術寫作、優質英文推薦與翻譯等等,歡迎關註哦。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 登高遠眺 滄海拾遺,積跬步以至千里 基礎技術 StackOverFlow 2020 年開發者報告 技術問答社區 StackOverFlow 的年度報告,本次報告統計了來自於全球各地共 65000 名開發者。有幾項數據令人震驚: 2020 年 jQuery 仍然是最受歡迎的 Web 開發者框架; Ru ...
  • 一、Overview Angular 入坑記錄的筆記第六篇,介紹 Angular 路由模塊中關於路由守衛的相關知識點,瞭解常用到的路由守衛介面,知道如何通過實現路由守衛介面來實現特定的功能需求,以及實現對於特性模塊的惰性載入 對應官方文檔地址: 路由與導航 配套代碼地址:angular-practi ...
  • 理解面向對象編程及面向對象編程語言的關鍵就是理解其四大特性:封裝、抽象、繼承、多態。不過,對於這四大特性,光知道它們的定義是不夠的,我們還要知道每個特性存在的意義和目的,以及它們能解決哪些編程問題 ...
  • Microsoft在2015年4月30日Build 開發者大會上正式宣佈了 Visual Studio Code 項目:一個運行於 Mac OS X、Windows和 Linux 之上的,針對於編寫現代 Web 和雲應用的跨平臺源代碼編輯器。現在的很多程式員也在利用VScode進行開發。接下來介紹如 ...
  • Java生鮮電商平臺-微服務生鮮電商系統設計(小程式/APP) 說明:本文章主要是講解-微服務生鮮電商系統設計與架構,希望對大家有所幫助 在實際業務場景中如何設計一套電商系統呢? 我們簡單想象一下,既然是一個電商系統,有用戶去購買,就肯定得有一個用戶模塊,購買什麼東西總不是西北風吧,購買肯定是商品吧 ...
  • 見到女朋友每次修改代碼都傻乎乎的重啟伺服器~~~你累不累,氣的我上去給了她一巴掌~~~。什麼時候了熱部署都不會,上教程!!! 1、idea設置自動編譯(設置在哪我就不說了) 2、ctrl+shift+alt+/,然後進去regist enter之後,找到這三個配置項,配置運行自動編譯和延遲更新毫秒數 ...
  • Ribbon客戶端組件提供一系列完善的配置選項,比如連接超時、重試、重試演算法等,內置可插拔、可定製的負載均衡組件。下麵是用到的一些負載均衡策略: 簡單輪詢負載均衡 加權輪詢負載均衡 區域感知輪詢負載均衡 隨機負載均衡 先寫一個類模擬一個IP列表: public class IpMap { // 待路 ...
  • 一、return語句 1.main函數有return語句,但是也可以沒有,對於main函數,運行完最後一行語句,就會自動自動返回一個0,但是其他函數是不可以的,為了養成好習慣,請在main函數末尾添加return 0; 2.return語句是一種跳轉語句。 3.舉例 #include <stdio. ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...