Python菜鳥晉級(基於Flask)2命名的藝術

来源:https://www.cnblogs.com/testing-/archive/2023/11/25/17848065.html
-Advertisement-
Play Games

十六、C++字元串(一) 1、原生字元串實現將兩個字元串拼接 //原生字元串實現將兩個字元串拼接 #include <iostream> #include <locale> int main() { char strA[0x10] = "123"; //定義字元串 char strB[0x10] = ...


2 命名的藝術

本章包括

  • 命名
  • 命名空間

"電腦科學中只有兩件難事:緩存失效和命名。"這句話出自菲爾-卡爾頓(Phil Karlton)之口,他是網景公司(Netscape)的程式員。

2.1 命名

命名是你和Python共用某物身份的一種方式。通常,這意味著您要唯一地標識一個事物,使其與程式中所有其他被命名的事物區分開來。例如,美國的社會安全號是給人們的,這樣他們就可以在美國的使用環境中唯一地識別自己。這串唯一的號碼可以幫助人們就業、納稅、購買保險,以及從事其他各種需要全國唯一標識符的活動。

這是否意味著社會保障號是唯一事物的好名字?其實不然。除非你能進入使用該號碼的系統,否則它是完全不透明的。它沒有傳遞任何關於所標識事物的信息。

讓我們把唯一名稱的概念提升到另一個層次。有一種標準化的標識符被稱為通用唯一標識符(UUID)。UUID是一串字元,就所有實際目的而言,在全世界都是唯一的。UUID示例如下

f566d4a9-6c93-4ee6-b3b3-3a1ffa95d2ae

您可以使用Python內置的UUID模塊,根據UUID值創建有效的變數名:

>>> import uuid
>>> f"v_{uuid.uuid4().hex}"
'v_02f9c8953e2d4fb8ba83b65f1237f82f'

您可以用這種方法創建變數名,以便唯一標識應用程式中的所有內容。這些變數名在整個應用程式中和已知世界中都是唯一的。

以這種方式命名變數也是一種完全不可用的命名約定。變數名完全沒有傳遞任何關於所標識事物的信息。這樣的變數名輸入起來也非常長,不可能記住,使用起來也不方便。

2.1.1 命名事物

創建有用的變數名需要花費精力,但作為開發人員,這是值得的。隨著時間的推移,你會發現變數名很難更改。這是因為隨著應用程式的開發和使用,對現有變數的依賴性會增加。選擇好的變數名可以避免在使用過程中更改變數名。

變數名的長度也與編寫代碼的工作量有關。編程確實涉及到大量的鍵入,這意味著意義和簡短之間的平衡非常重要。

你突然發現,整個語言都是你尋找命名單詞和短語的地方。您的目標是找到既能附加元信息,又足夠簡短,不會妨礙編寫或閱讀一行程式代碼的詞語。這就限制了你在命名時可以或應該做的事情。就像畫家在有限的調色板上創作一樣,你可以選擇沮喪,也可以在這種限制下發揮想象力,創作出具有藝術性和創造力的作品。

你要編寫的許多程式都會包括對事物集合的迴圈、計數和相加。下麵是一個二維表格的迭代代碼示例:

t = [[12, 11, 4], [3, 22, 105], [0, 47, 31]]
for i, r in enumerate(t):
    for j, it in enumerate(r):
        process_item(i, j, it)

這段代碼功能完善。t 變數由一個 Python 列表組成,代表一個二維表格。process_item() 函數需要知道項目--it 變數--在表中的行和列位置,才能正確處理它。變數 t、i、j、r 和 it 完全可以使用,但卻沒有告訴讀者它們的意圖。

修改後:

table = [[12, 11, 4], [3, 22, 105], [0, 47, 31]]
for row_index, row in enumerate(table):
    for column_index, item in enumerate(row):
        process_item(row_index, column_index, item)

開發過程中的另一個常見操作是計數和創建總數。下麵是一些簡單的示例:

total_employees = len(employees)
total_parttime_employees = len([
    employee for employee in employees if employee.part_time
])
total_managers = sum([
    employee for employee in employees if employee.manager
])

在前面的示例中,我們可以看到幾個非常好的命名規則。employees 這個名字賦予了變數意義。複數 employees的使用表明這是可迭代的集合。它還表明該集合內部有一個或多個代表雇員的事物。列表理解中的變數employee表明它是雇員集合中的單個項目。

變數total_employees、total_parttime_employees和total_ managers的名稱中使用了total,說明瞭它們所指的是什麼。每一個變數都是一個總計數。每個變數名的第二部分表示被計算的事物。

除了數值計算,你還經常會遇到一些已經有名字的事物,比如公司、社區或小組中的人。當你收集用戶輸入或通過名字搜索某人時,有一個有用的變數名會讓你更容易想到代碼中要表示的事物:

full_name = "John George Smith"

根據您編寫代碼的目的,這可能是一個完全可以接受的變數名,用來表示姓名。通常情況下,在處理人名時,您需要更細化的變數名,並希望用部分變數名來表示人名:

first_name = "John"
middle_name = "George"
last_name = "Smith"

這些變數名也能很好地發揮作用,而且與full_name一樣,這些變數名賦予了變數所代表的含義。下麵是另一種變體

fname = "John"
mname = "George"
lname = "Smith"

這個版本採用了變數命名的慣例。這樣的約定意味著你選擇了一種模式來創建人的變數名。使用約定意味著讀者必須知道並理解所使用的約定。上例中的折衷方法是減少鍵入,但變數名的含義仍然清晰。此外,由於變數名以單行編輯字體垂直排列,因此視覺效果可能更好。

採用約定是在變數命名限制條件下提高工作效率的一種技巧。如果速記命名約定在視覺上對你更有吸引力,那麼在可視化解析代碼時,你就能識別模式並找出錯別字。

建立約定俗成的習慣有助於減輕開發人員的認知負擔。你可以更多地考慮要解決的問題,而不是考慮如何命名。

2.1.2 命名實驗

你可能不記得了,早期的個人電腦只有很小的硬碟驅動器。早期的操作系統也沒有目錄或子目錄的概念;硬碟上的所有文件都存在於一個全局目錄中。此外,文件名僅限於8個字元、點(.)和 3 個字元的擴展名,擴展名通常用來表示文件包含的內容。

正因為如此,人們發明瞭奇異而複雜的文件命名約定,以保持唯一性並防止文件名衝突。這些命名約定是以犧牲有邏輯意義的文件名為代價的。例如1995年10月創建的簡歷文件可能是這樣的

res1095.doc

解決這個問題的辦法是在操作系統中增加對命名子目錄的支持,並取消文件名字元長度限制。現在,每個人都對此非常熟悉,因為你可以創建幾乎無限深的目錄和子目錄結構。

下麵是一個要求你滿足的規範:你工作的會計部門要求所有費用報告的文件名都必須相同:expense.xlsx。你需要創建一個目錄結構,讓所有expenses.xlsx文件都能存在,並且不會相互碰撞或覆蓋,以保存和跟蹤這些費用文件。

約束條件是要求所有支出報告文件都有一個固定的文件名。隱含的限制條件是,無論你設計什麼樣的目錄結構,都必須適用於你的工作所產生的儘可能多的費用報告。創建子目錄的功能就是幫助你解決這個問題並將費用報告文件分開的工具。

任何解決方案都取決於你在工作中創建了多少份開支報告。如果你的工作是初級軟體開發人員,你可能一年只出差幾次。在這種情況下,你只需提供粗粒度的支出.xlsx文件,就可以將其分開。這種簡單的結構將所有支出報告集中在一個名為expenses的根目錄下。每份費用報告都存在於一個目錄中,該目錄以創建費用報告的完整日期命名。使用YYYY-MM-DD的日期格式會使目錄在許多操作系統上顯示時按有用的時間順序排序。

但是,如果你是一名銷售工程師,你很可能經常出差,可能每天要會見多個客戶。這就改變了你處理約束的方式,要求你的目錄結構支持更多的粒度,以便將所有expenses.xlsx文件分開。對於銷售工程師來說,一個可行的解決方案是使用年、月、日和客戶名稱值作為子目錄。這樣,即使每天拜訪多個客戶,也能保持expenses.xlsx文件的獨立性。這樣就形成了一種慣例,即特定expenses.xlsx文件路徑的每一部分都有意義和價值。

從前面的實驗中我們可能看不出什麼,但我們創建的變數名是有意義和約定俗成的。請看特定支出報告的目錄路徑。你創建了命名空間,每個命名空間都縮小了所包含內容的範圍。從左到右閱讀路徑,你會發現路徑的每一段都由 / 字元分隔,在前一段的上下文中創建了一個新的、範圍更小的命名空間。

假設你是會計師,規定了費用報告的文件命名規則。作為會計,你必須保存員工提交的所有費用報告。你將受到與生成費用報告的員工相同的限制,但要保持所有員工的費用報告彼此不同並相互分離,這就增加了複雜性。

創建一個目錄結構來處理增加的複雜性,可以包括更高級別的部門和員工抽象。創建一個提供這種粒度的目錄結構來跟蹤和保存所有員工費用報告是可行的。考慮到如何創建該結構,會計部門顯然應該重新考慮文件命名要求和限制,並設計一個更好的系統。

2.2 命名空間

Python編程語言提供了創建名稱空間的能力。在處理命名變數的約束、賦予它們意義、保持它們相對較短並避免衝突時,命名空間為您提供了很大的能力和控制。可以通過在命名空間放置變數名來實現這一點。在開始創建自己的命名空間之前,讓我們先看看該語言提供的名稱空間。

2.2.1內置級

當Python開始運行應用程式時,它會創建一個builtins命名空間,其中builtins是Python中最外層的命名空間,包含您可以隨時訪問的所有函數。例如,print()和open()函數存在於內置命名空間中。

你可以通過在Python交互提示符下輸入以下命令來查看內置命名空間中的內容:

>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EncodingWarning', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'aiter', 'all', 'anext', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

該命令在__builtins__對象上運行dir (directory)。

在使用內置命名空間時,完全有可能用您自己的命名空間覆蓋名稱空間中的對象。例如,你可以這樣定義一個函數:

def open(...):
    # run some code here

這個函數遮蔽了已經在內置命名空間中定義的open()函數。你可以通過創建如下的函數來處理這個問題:

def my_own_open(...):
    # run some code here

參考資料

2.2.2模塊級別

將程式代碼分解為包含邏輯分組功能的多個文件是一種有用的慣例。這樣做有以下好處:

  • 將相似的功能放在一起
  • 防止程式文件變得太長
  • 創建命名空間

utility.py:

def add(a, b):
    return f"{a} {b}"

main.py

import utility 
 
def add(a, b):
    return a + b
 
print(add(12, 12))
print(utility.add(12, 12))

utility.py文件將兩個add()函數定義分開。在main.py文件中,import utility語句告訴Python將utility.py文件中的所有對象拉到utility的新名稱空間中。

在導入文件時使用from import *表單通常不是一個好主意。

通過利用文件系統目錄結構,您可以創建名稱空間層次結構。就像前面的目錄結構命名實驗一樣,這為您提供了更多的工具來為您創建的層次結構創建意義和範圍。

在main.py文件所在的文件夾中創建utilities的新目錄。將utility.py文件移動到utilities目錄,並將其重命名為strings.py。

在創建包含功能的目錄層次結構時,需要記住的一件事是需要創建一個__init__.py文件。該文件必須存在於每個目錄中,以讓Python知道該目錄包含功能或它的路徑。當__init__.py文件存在於目錄中時,該目錄就是Python包。

通常__init__.py文件是空的,但它不必是空的。只要包含該文件的路徑是import語句的一部分,該文件中的任何代碼都將執行。

在此基礎上,在實用程式目錄中創建一個空的__init__.py文件。完成後,像這樣修改main.py文件:

from utilities import strings
 
def add(a, b):
    return a + b
 
print(add(12, 12))
print(strings.add(12, 12))

如果您使用過任何Python的標準模塊,如sys,您可能會註意到這些標準模塊不存在於您的程式的工作目錄中,例如您之前創建的strings.py模塊。Python通過路徑列表搜索你想要導入的模塊,首先是工作目錄。

>>> import sys
>>> sys.path
['', 'D:\\anaconda\\python310.zip', 'D:\\anaconda\\DLLs', 'D:\\anaconda\\lib', 'D:\\anaconda', 'C:\\Users\\徐榮中\\AppData\\Roaming\\Python\\Python310\\site-packages', 'D:\\anaconda\\lib\\site-packages', 'D:\\anaconda\\lib\\site-packages\\win32', 'D:\\anaconda\\lib\\site-packages\\win32\\lib', 'D:\\anaconda\\lib\\site-packages\\Pythonwin']

列表中的第一個元素是一個空字元串。Python將在當前工作目錄中查找模塊。這就是它找到utilities包和該包中string模塊的方式。

這也意味著,如果你創建了一個模塊,並將其命名為Python系統模塊,Python將首先找到你的包並使用它,而忽略系統包。在命名包和模塊時,請記住這一點。

在我們的簡短示例中,import sys語句導致Python搜索前面提到的路徑列表。因為工作目錄中不存在sys模塊,所以它會在其他路徑中查找標準模塊。

路徑列表在使用pip命令安裝包或模塊時使用。pip命令將在列表中的一個路徑中安裝包。如前所述,建議使用Python虛擬環境來防止pip安裝到您的電腦系統的Python版本中。

釘釘或微信號: pythontesting 微信公眾號:pythontesting
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文是對這篇文章MySQL InnoDB Cluster - Navigating the Cluster[1]的翻譯,翻譯如有不當的地方,敬請諒解,請尊重原創和翻譯勞動成果,轉載的時候請註明出處。謝謝! 當我們管理InnoDB Cluster時,一件非常重要的事情就是瞭解集群處於什麼樣的狀態,特別 ...
  • 副本集概述 副本集(Replica Set)是一組帶有故障轉移的 MongoDB 實例組成的集群,由一個主(Primary)伺服器和多個從(Secondary)伺服器構成。通過Replication,將數據的更新由Primary推送到其他實例上,在一定的延遲之後,每個MongoDB實例維護相同的數據 ...
  • 最近接觸到了一個問題:耳機插入事件的由來,走讀了下IMS輸入系統服務的源碼。同時,IMS輸入系統服務在Android的開發過程中,也經常出現,有必要瞭解下相關原理。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 最近喜歡研究起了手錶,對勞力士這款“百事圈”實在是心水的不行啊! 心癢難耐無奈錢包不支持,作為一個前端程式員,買不起的東西該怎麼辦? 當然是自己做一個啊! 說乾就乾,熬夜自己做了個“百事圈”出來!源碼在最後! 先看成品 還是有那麼六七成相 ...
  • 沒有什麼是不可能的,只是需要找到正確的方法。 1. 什麼是狀態? 狀態就是組件內部特有數據的載體(組件數據掛載方式),改變數據頁面就會刷新,由組件自己設置和更改,也就是說由組件自己產生、維護,使用狀態的目的就是為了在不同的狀態下使組件的顯示不同(自己管理),這在 React 中稱為:條件渲染。 為什 ...
  • Node.js是一個基於ChromeV8引擎的JavaScript運行環境,使用了一個事件驅動、非阻塞式I/O模型,讓JavaScript 運行在服務端的開發平臺,它讓JavaScript成為與PHP、Python、Perl、Ruby等服務端語言平起平坐的腳本語言。Node中增添了很多內置的模塊,提... ...
  • Promise對象用於清晰的處理非同步任務的完成,返回最終的結果值,本次分享主要介紹Promise的基本屬性以及Promise內部的基礎實現,能夠幫我們更明確使用場景、更快速定位問題。 ...
  • 公眾號「架構成長指南」,專註於生產實踐、雲原生、分散式系統、大數據技術分享。 資料庫和Redis如何保持強一致性,這篇文章告訴你 目的 Redis和Msql來保持數據同步,並且強一致,以此來提高對應介面的響應速度,剛開始考慮是用mybatis的二級緩存,發現坑不少,於是決定自己搞 要關註的問題點 操 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...