[譯]Python手冊——模塊

来源:http://www.cnblogs.com/crazyrunning/archive/2017/06/16/7027886.html
-Advertisement-
Play Games

The Python Tutorial » 6. Modules 翻譯 ...


[譯]The Python Tutorial#Modules

6. Modules

如果你從Python解釋器中退出然後重新進入,之前定義的名字(函數和變數)都丟失了。因此,如果你想寫長一點的程式,使用文本編輯器來準備解釋器的輸入會更好,使用文件作為替代的輸入。這也被稱作創建腳本。當程式越來越長時,出於易於維護的原因,你可能會將程式分割為幾個文件。你也可能想要在多個程式中使用很好用的一個函數,而不用將其定義拷貝到每一個程式中。

為了支持這些需求,Python提供了將定義放入一個文件的方式,並且在腳本或者解釋器互動式實例中使用它們。這樣的文件稱為模塊;模塊中的定義可以導入到其他模塊或者主模塊中(在頂層執行的腳本和計算模式中可訪問到的變數集合)。

模塊就是一個包含Python定義和語句的文件。文件名是模塊名並且帶有.py尾碼。在模塊中,模塊的名字(作為字元串),作為全局變數__name__的值,是可用的。例如,使用你最喜歡的文本編輯器在當前目錄創建fibo.py文件,內容如下:

# Fibonacci numbers module

def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

def fib2(n):   # return Fibonacci series up to n
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a+b
    return result

進入Python解釋器,使用下列命令導入這個模塊:

>>> import fibo

這個操作並不會講fibo中定義的函數的名字導入到當前符號表中;只是導入模塊的名字fibo。使用模塊名字可訪問到函數:

>>> fibo.fib(1000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'

如果想要頻繁使用函數,可以將其賦值給局部名字:

>>> fib = fibo.fib
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

6.1 More on Modules

模塊可以同時包含可執行語句和函數定義。可執行語句用來初始化模塊。當模塊名字出現在導入語句中時,這些可執行語句只執行一次[1]。(如果文件作為腳本,這些可執行也會執行)

每一個模塊都有自己私有的符號表,這個符號表被所有定義在模塊中的函數作為全局符號表使用。因此,模塊的作者可以使用這些全局變數,而不用擔心和用於全局變數偶然的名字衝突。另一方面,如果你知道自己在做什麼,你可以使用與引用函數相同的方法來引用模塊的全局變數,modname.itemname

模塊可以引用其他模塊。將所有import語句放置到模塊的開始處(或者腳本)是一個很好的習慣,但並不是強制的。被導入的模塊名字將會被放置到當前模塊的全局符號表中。

有一種導入語句的變種方法,將模塊的名字直接導入到當前模塊的符號表中。例如:

>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

以上並不會引入模塊的名字(在上面的例子中fibo不會被定義)。

甚至有一種方法可以導入模塊中定義的所有名字:

>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

這種方法導入所有不以下劃線_開頭的名字。大多數情況下,Python程式員不會使用這種方法,因為這會導入未知的名字集合到解釋器中,也許還會屏蔽已經定義的一些名字。

需要註意,通常在實踐中從模塊或者包中導入所以名字是不鼓勵使用的,因為會降低程式的易讀性。然而,在互動式環境中使用它來減少打字輸入是可行的。

註意: 出於性能原因,一個解釋器會話中每個模塊只導入一次。因此,如果模塊被改變了,必須重啟解釋器;如果只想要互動式測試一個模塊,使用 importlib.reload(),例如:import importlib; importlin.reload(modulename)

6.1.1 Executing modules as scripts

當使用以下命令運行Python模塊:

python fibo.py <arguments>

模塊中的代碼會被執行,就像導入該模塊一樣,但是這時__name__被設置為__main__。這意味著以下代碼會加入到模塊末尾:

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

模塊即作為腳本執行,也可以作為模塊導入,因為只有當模塊作為mian文件執行時候,解析命令行的代碼才會執行:

$ python fibo.py 50
1 1 2 3 5 8 13 21 34

如果模塊被導入,代碼不會執行:

>>> import fibo
>>>

這可以用來為使用者提供一個模塊用戶介面的使用約定,也可以用作測試(模塊作為腳本時執行測試用例)

6.1.2 The Module Search Path

當模塊spam被導入時,解釋器首先搜索built-in模塊。如果沒有找到,解釋器在變數sys.path提供的路徑列表中搜索名為spam.py的文件。sys.path從下列位置初始化:

  • 包含輸入腳本的目錄(或者沒有指定文件時的當前目錄)
  • PYTHONPATH(目錄名字集合,與shell環境變數PATH相似,也是環境變數)
  • 安裝預設目錄

註意: 在支持符號鏈接的文件系統,包含輸入腳本的目錄是符號鏈接指向的目錄。也就是說包含符號鏈接的目錄不會被加入到搜索路徑中。

初始化後,Python程式可以修改sys.path。包含執行腳本的目錄被放置到搜索路徑的開始,在標準庫路徑之前。這意味著該目錄中的腳本會被載入,而標準庫目錄中的同名模塊不會被載入。這會引發錯誤,除非是有意替換標準庫的模塊。閱讀Standard Modules獲取更多信息。 (譯註:自定義的模塊不應與標準模塊重名,否則標準模塊會被覆蓋。)

6.1.3 “Compiled” Python files

為加速模塊載入,Python會在__pycache__目錄中緩存每個模塊的編譯版本,緩存文件名為module.version.pycversion編碼了被編譯文件的版本;通常包含了Python的版本號。例如,在CPython release 3.3中,文件spam.py的編譯版本會被緩存為__pycache__/spam.cpython-33.pyc。這種命名約定允許來自不同Python發行版本的模塊得以共存。

Python檢查源文件的修改日期與編譯版本,來確定編譯版本是否過期,是否需要重新編譯。這是一個完全自動化的過程。另外,編譯模塊是平臺獨立的,因此異構系統可以共用相同的庫。

Python不會檢查在兩個環境中的緩存。首先,Python總是重新編譯,並且不會存儲直接從命令行載入的模塊的結果。其次,如果沒有源模塊,Python不檢查緩存。若要支持無源文件(只有編譯版本)分佈,那麼編譯的模塊必須放在源文件目錄中,並且源模塊必需不存在。

給專家的建議:

  • 可以在命令行使用-O或者-OO開關來減少編譯模塊的大小。-O參數移除assert語句,-OO參數同時移除assert語句和__doc__字元串。由於一些程式依賴這些變數,那麼只有當你確認你要這麼做時,才能使用這兩個參數。“優化的”模塊有一個opt-標簽並且通常更小。未來的髮型版本可能改變優化的影響。
  • .pyc文件中讀取的程式不會比從.py文件讀取的程式跑得快;.pyc文件快的地方在於載入。
  • compileall模塊可以為目錄中的所有模塊創建.pyc文件。
  • PEP 3147中有關係這點的更多信息,包括一個決策流程

6.2 Standard Modules

Python提供了標準模塊庫,在獨立文檔中描述,名為Python Library Reference(以後叫做Library Reference)。有一些模塊內嵌入解釋器中,這些模塊不是語言核心的一部分,但是它們是內嵌的,這既是為性能考慮,也提供了訪問如系統調用般的操作系統原生介面的方式。這些模塊集合依賴底層平臺的配置選項。例如winreg模塊只在Windows系統中提供。一個特殊的模塊值得註意:sys,這個模塊內嵌在所有Python解釋器中。變數sys.ps1sys.ps2定義了主提示符和輔助提示符的字元串:

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>

只有當解釋器以交互模式運行才會定義這兩個變數。

變數sys.path是決定解釋器模塊搜索路徑的字元列表。該變數從環境變數PYTHONPATH,或者內置預設路徑(PYTHONPATH未指定時)初始化。可以使用標準list操作修改它的值:

>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')

6.3 The dir() Function

內嵌函數dir()用於搜索模塊定義的名字。返回一個有序字元串列表:

>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)  
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
 '__package__', '__stderr__', '__stdin__', '__stdout__',
 '_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
 '_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
 'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
 'call_tracing', 'callstats', 'copyright', 'displayhook',
 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
 'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
 'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
 'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
 'thread_info', 'version', 'version_info', 'warnoptions']

不帶參數使用dir()函數,會列出當前作用域的全部名字:

>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']

需要註意該函數列出所有類型的名字:變數,模塊,函數,等等。

dir()不會列出內嵌函數和變數的名字。如果希望列出,這些名字定義在標準模塊builtins中:

>>> import builtins
>>> dir(builtins)  
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
 'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
 'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError',
 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
 '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
 'all', 'any', 'ascii', 'bin', 'bool', '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']

6.4 Packages

包是使用“圓點模塊名”結構化Python模塊名字空間的方式。例如,模塊名A.B表示包A中的子模塊B。就像模塊使得不同模塊的作者免於擔憂每個模塊的全局名字一樣,圓點模塊名的使用使得多模塊包(如NumPy或者Python圖像庫)的作者免於擔憂每個模塊的名字。

假設需要為統一音頻文件和音頻數據的處理設計一個模塊的集合(包)。有許多不同的音頻文件格式(通常通過擴展名辨認,如.wav, .aiff, .au),因此需要為不同文件格式的轉換創建和維護一個持續增長的模塊集合。也存在許多對音頻數據不同的操作(例如混合,增加回聲,增加均衡器函數,創建人造立體效果),因此需要額外編寫執行這些操作的大量模塊。以下是包的可能結構(以層級文件結構來表示):

sound/                          Top-level package
      __init__.py               Initialize the sound package
      formats/                  Subpackage for file format conversions
              __init__.py
              wavread.py
              wavwrite.py
              aiffread.py
              aiffwrite.py
              auread.py
              auwrite.py
              ...
      effects/                  Subpackage for sound effects
              __init__.py
              echo.py
              surround.py
              reverse.py
              ...
      filters/                  Subpackage for filters
              __init__.py
              equalizer.py
              vocoder.py
              karaoke.py
              ...

導入包時,Python搜索sys.path提供的路徑尋找包子目錄。

為使Python將普通目錄看做包,目錄中必須包含__init__.py文件。這樣做是為了避免普通的目錄名(如string)將以後會出現在模塊搜索路徑中的有效模塊無意識的隱藏掉。最簡單的情況是,__init__.py可以是一個空文件,但是它也可以包含可執行的初始化包的代碼或者設置__all__變數,後面講述。

包的用戶可以從包中導入獨立的模塊:

import sound.effects.echo

這將加在子模塊sound.effects.echo。必須使用全名引用:

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

導入子模塊可選方式:

from sound.effects import echo

以上也載入子模塊echo,不使用包首碼引用模塊,因此可以像下麵一樣使用:

echo.echofilter(input, output, delay=0.7, atten=4)

另外的方式是直接導入需要的函數或者變數:

from sound.effects.echo import echofilter

同樣的,這將加在子模塊echo,但使函數echofilter()直接可用:

echofilter(input, output, delay=0.7, atten=4)

註意當使用from package import item時,item可以使子模塊(子包),也可以是包內定義的其他名字,如函數,類或者變數。import語句首先測試要導入的項是否在包中存在;如果不存在,Python假設這個項是模塊並嘗試載入它。如果最後尋找失敗,ImportError異常拋出。

相對的,使用import item.subitem.subsubitem時,除了最後一項,每一項都必須是包;最後一項可以是模塊或者包但是不能是前面的項中定義的類,函數或者變數。

6.4.1 Importing * From a Package

使用from sound.effects import *會發生什麼?理想情況下,總是期望在文件系統中找出所有子模塊,並全部導入。全部導入會耗費很長時間,並且導入子模塊可能會有不期待的副作用,這些副作用應該在顯式導入時發生。

唯一的解決方案是包作者提供一個包的顯式索引。import語句遵循以下約定:如果包的__init__.py代碼中定義了名為__all__的變數,那麼使用from package import *時會導入該變數指定的所有模塊。當包的新版本發佈時,由包作者負責更新列表__all__。如果包作者不希望可以使用from package import *導入包中的模塊,也可以不支持__all__。 例如,文件sound/effects/__init__.py可能包含以下代碼:

__all__ = ["echo", "surround", "reverse"]

這意味著from sound.effects import *會導入sound包中指定的三個模塊。

如果__all__沒有定義,語句from sound.effects import *不會將包sound.effects中的子模塊全部倒入到當前名字空間中,只保證包sound.effects被導入了(可能會運行__init__.py中的初始化代碼)並且導入任意在包中定義的名字。包括在__init__.py中定義的任意名字(以及顯式載入的子模塊)。也會包括前面的import語句顯式載入的任意包子模塊。考慮如下代碼:

import sound.effects.echo
import sound.effects.surround
from sound.effects import *

這個例子中,echosurround模塊被導入到當前名字空間中,因為執行from... import時,它們已經定義在sound.effects包中定義了。(定義了__all__時同樣有效)

儘管使用import *時只有符合特定模式的名字會被導出,但仍然不建議在生產代碼中使用。

記住,使用form Package import specific_submodle沒有錯誤。實際上,這是推薦的方法,除非當前模塊需要使用其他包中的同名模塊。

6.4.2 Intra-package References

當包中包含了子包結構(就如例子中的sound包),可以使用絕對導入的方式引用兄弟包中的子模塊。例如,如果模塊sound.filters.vocoder需要使用包sound.effects中的echo模塊,可以使用from sound.effects import echo

也可以使用from modul import name語句來相對導入模塊。這種方式使用點.指示當前包和相對導入中涉及的父包。以surround模塊為例:

from . import echo
from .. import formats
from ..filters import equalizer

相對導入基於當前模塊的名字。由於主模塊的名字總是__main__,要當做Python應用主模塊使用的模塊必須總是使用絕對導入的方式。

6.4.3 Packages in Multiple Directories

包還支持一個特殊屬性,__path__。在__init__.py中的代碼執行之前,屬性__path__被初始化為一個列表,這個列表包含了持有該__init__.py文件的目錄的路徑。該變數可修改,這樣做會影響將來的對包內模塊和子包的搜索。

然而這個特性不總是需要的,它可以用來擴展包的模塊集合

Footnotes

[1] 實際上,函數定義也是可“執行”的“語句”;模塊級別的函數執行將函數的名字放置到模塊的全局符號表中


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

-Advertisement-
Play Games
更多相關文章
  • 題目描述 牛牛最近迷上了一種叫鬥地主的撲克游戲。鬥地主是一種使用黑桃、紅心、梅花、方片的A到K加上大小王的共54張牌來進行的撲克牌游戲。在鬥地主中,牌的大小關係根據牌的數位表示如下:3<4<5<6<7<8<9<10<J<Q<K<A<2<小王<大王,而花色並不對牌的大小產生影響。每一局游戲中,一副手牌 ...
  • Java的記憶體分配上,主要分4個塊!一塊是用來裝代碼的,就是編譯的東西。一塊是用來裝靜態變數的,例如用static關鍵字的變數,例如字元串常量。一塊是stack,也就是棧,是用來裝變數和引用類型的!但區別在於,裝了變數以後,變數上是有值的,而引用類型本身在stack上是沒有值的。一塊是heap,也就 ...
  • 今天使用ab(apacheBench)測試了一下beego的性能。 3Kbytes動態文件,在i3上可以達到每秒1W次響應的性能。但是在測試靜態文件時,beego出現了問題。ab測試參數:100次請求,併發數5。問題表現:70%的請求直接失敗,連接斷開。按道理來說,一個web server框架,靜態 ...
  • 整個項目只有四張表 book-書籍主表,記錄書籍的詳情信息,包括類別,作者描述等 type-類別表,書籍類別管理 menu-目錄章節表 properties-配置表 book表是書籍主表 code:用於圖書code記錄,可認為該欄位能確定圖書唯一 typeId:關聯type表主鍵id,標識圖書類別 ...
  • 之所以將抽象類和介面放在一起做筆記,是因為他們之間很難區分又各自獨立。在學習完Java程式設計的三大特點(封裝、繼承、多態)之後,我最大的收穫是,慢慢理解了Java語言這種面向對象程式設計的優越性,它既能保持自身獨立性又在不斷進化、發展的。如果說封裝和繼承是實現Java多態性的基礎,那我個人覺得抽象 ...
  • <?php // 暫不支持斷點續傳 // $url = 'http://www.mytest.com/debian.iso'; 不知道為何獲取本地文件大小為0 $url = 'http://192.168.8.93/download/vm-672/18/0.vmdk'; $file = basena... ...
  • 題目描述 野貓與胖子,合起來簡稱肥貓,是一個班的同學,他們也都是數學高手,所以經常在一起討論數學問題也就不足為奇了。一次,野貓遇到了一道有趣的幾何游戲題目,便拿給胖子看。游戲要求在一個有n個頂點凸多邊形上進行,這個凸多邊形的n-3條對角線將多邊形分成n-2個三角形,這n-3條對角線在多邊形的頂點相交 ...
  • 1. 把‘2016-06-16’格式轉換成‘20160616’ 2. 按日期 YYYY-MM-DD 格式 “2016-06-16 00:00:00” 查詢今日內容。需拼接今日起始時間。 3. php中查詢sql 把時間轉換成unix時間戳進行比較; ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...