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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...