国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 你可能不知道的Python技巧

你可能不知道的Python技巧

2021-01-06 23:16機器學習算法與Python學習 Python

有許許多多文章寫了 Python 中的許多很酷的特性,例如變量解包、偏函數、枚舉可迭代對象,因此在本文中,我將嘗試展示一些我知道的和在使用的,但很少在其它文章提到過的特性。那就開始吧。

你可能不知道的Python技巧

有許許多多文章寫了 Python 中的許多很酷的特性,例如變量解包、偏函數、枚舉可迭代對象,但是關于 Python 還有很多要討論的話題,因此在本文中,我將嘗試展示一些我知道的和在使用的,但很少在其它文章提到過的特性。那就開始吧。

1、對輸入的字符串“消毒”

對用戶輸入的內容“消毒”,這問題幾乎適用于你編寫的所有程序。通常將字符轉換為小寫或大寫就足夠了,有時你還可以使用正則表達式來完成工作,但是對于復雜的情況,還有更好的方法:

  1. user_input = "This  
  2. string has  some whitespaces...  
  3.  
  4. character_map = {  
  5.  ord(   
  6.  ) :    ,  
  7.  ord(    ) :    ,  
  8.  ord(   
  9.  ) : None  
  10.  
  11. user_input.translate(character_map)  # This string has some whitespaces... " 

在此示例中,你可以看到空格字符“ ”和“ ”被單個空格替換了,而“ ”則被完全刪除。這是一個簡單的示例,但是我們可以更進一步,使用unicodedata 庫及其 combining() 函數,來生成更大的重映射表(remapping table),并用它來刪除字符串中所有的重音。

2、對迭代器切片

如果你嘗試直接對迭代器切片,則會得到 TypeError ,提示說該對象不可取下標(not subscriptable),但是有一個簡單的解決方案:

  1. import itertools  
  2. s = itertools.islice(range(50), 10, 20)  # <itertools.islice object at 0x7f70fab88138>  
  3. for val in s:  
  4.  ... 

使用itertools.islice,我們可以創建一個 islice 對象,該對象是一個迭代器,可以生成我們所需的內容。但是這有個重要的提醒,即它會消耗掉切片前以及切片對象 islice 中的所有元素。

(譯注:更多關于迭代器切片的內容,可閱讀Python進階:迭代器與迭代器切片)

3、跳過可迭代對象的開始

有時候你必須處理某些文件,它們以可變數量的不需要的行(例如注釋)為開頭。itertools 再次提供了簡單的解決方案:

  1. string_from_file = "" 
  2. // Author: ...  
  3. // License: ...  
  4. //  
  5. // Date: ...  
  6. Actual content...  
  7. """  
  8. import itertools  
  9. for line in itertools.dropwhile(lambda line:line.startswith("//"), string_from_file.split("  
  10. ")):  
  11.     print(line) 

這段代碼僅會打印在初始的注釋部分之后的內容。如果我們只想丟棄迭代器的開頭部分(在此例中是注釋),并且不知道有多少內容,那么此方法很有用。

4、僅支持關鍵字參數(kwargs)的函數

當需要函數提供(強制)更清晰的參數時,創建僅支持關鍵字參數的函數,可能會挺有用:

  1. def test(*, a, b):  
  2.  pass  
  3. test("value for a", "value for b")  # TypeError: test() takes 0 positional arguments...  
  4. test(a="value"b="value 2")  # Works... 

如你所見,可以在關鍵字參數之前,放置單個 * 參數來輕松解決此問題。如果我們將位置參數放在 * 參數之前,則顯然也可以有位置參數。

5、創建支持 with 語句的對象

我們都知道如何使用 with 語句,例如打開文件或者是獲取鎖,但是我們可以實現自己的么?是的,我們可以使用__enter__ 和__exit__ 方法來實現上下文管理器協議:

  1. class Connection:  
  2.  def __init__(self):  
  3.   ...  
  4.  def __enter__(self):  
  5.   # Initialize connection...  
  6.  def __exit__(self, type, value, traceback):  
  7.   # Close connection...  
  8. with Connection() as c:  
  9.  # __enter__() executes  
  10.  ...  
  11.  # conn.__exit__() executes 

這是在 Python 中實現上下文管理的最常見方法,但是還有一種更簡單的方法:

  1. from contextlib import contextmanager  
  2. @contextmanager  
  3. def tag(name):  
  4.  print(f"<{name}>")  
  5.  yield  
  6.  print(f"</{name}>")  
  7. with tag("h1"):  
  8.  print("This is Title.") 

上面的代碼段使用 contextmanager 裝飾器實現了內容管理協議。tag 函數的第一部分(yield 之前)會在進入 with 語句時執行,然后執行 with 的代碼塊,最后會執行 tag 函數的剩余部分。

5、用__slots__節省內存

如果你曾經編寫過一個程序,該程序創建了某個類的大量實例,那么你可能已經注意到你的程序突然就需要大量內存。那是因為 Python 使用字典來表示類實例的屬性,這能使其速度變快,但內存不是很高效。通常這不是個問題,但是,如果你的程序遇到了問題,你可以嘗試使用__slots__ :

  1. class Person:  
  2.     __slots__ = ["first_name", "last_name", "phone"]  
  3.     def __init__(self, first_name, last_name, phone):  
  4.     self.first_name = first_name 
  5.     self.last_name = last_name  
  6.     self.phone = phone 

這里發生的是,當我們定義__slots__屬性時,Python 使用固定大小的小型數組,而不是字典,這大大減少了每個實例所需的內存。使用__slots__還有一些缺點——我們無法聲明任何新的屬性,并且只能使用在__slots__中的屬性。同樣,帶有__slots__的類不能使用多重繼承。

6、限制CPU和內存使用量

如果不是想優化程序內存或 CPU 使用率,而是想直接將其限制為某個固定數字,那么 Python 也有一個庫能做到:

  1. import signal  
  2. import resource  
  3. import os  
  4. # To Limit CPU time  
  5. def time_exceeded(signo, frame):  
  6.  print("CPU exceeded...") 
  7.  raise SystemExit(1)  
  8. def set_max_runtime(seconds):  
  9.  # Install the signal handler and set a resource limit  
  10.  soft, hard = resource.getrlimit(resource.RLIMIT_CPU)  
  11.  resource.setrlimit(resource.RLIMIT_CPU, (seconds, hard))  
  12.  signal.signal(signal.SIGXCPU, time_exceeded)  
  13. # To limit memory usage  
  14. def set_max_memory(size):  
  15.  soft, hard = resource.getrlimit(resource.RLIMIT_AS)  
  16.  resource.setrlimit(resource.RLIMIT_AS, (size, hard)) 

在這里,我們可以看到兩個選項,可設置最大 CPU 運行時間和內存使用上限。對于 CPU 限制,我們首先獲取該特定資源(RLIMIT_CPU)的軟限制和硬限制,然后通過參數指定的秒數和先前獲取的硬限制來設置它。最后,如果超過 CPU 時間,我們將注冊令系統退出的信號。至于內存,我們再次獲取軟限制和硬限制,并使用帶有 size 參數的setrlimit 和獲取的硬限制對其進行設置。

8、控制可以import的內容

某些語言具有非常明顯的用于導出成員(變量、方法、接口)的機制,例如Golang,它僅導出以大寫字母開頭的成員。另一方面,在 Python 中,所有內容都會被導出,除非我們使用__all__ :

  1. def foo():  
  2.  pass  
  3. def bar(): 
  4.  pass  
  5. __all__ = ["bar"] 

使用上面的代碼段,我們可以限制from some_module import * 在使用時可以導入的內容。對于以上示例,通配導入時只會導入 bar。此外,我們可以將__all__ 設為空,令其無法導出任何東西,并且在使用通配符方式從此模塊中導入時,將引發 AttributeError。

9、比較運算符的簡便方法

為一個類實現所有比較運算符可能會很煩人,因為有很多的比較運算符——__lt__、__le__、__gt__ 或__ge__。但是,如果有更簡單的方法呢?functools.total_ordering 可救場:

  1. from functools import total_ordering  
  2. @total_ordering  
  3. class Number:  
  4.  def __init__(self, value):  
  5.   self.value = value  
  6.  def __lt__(self, other):  
  7.   return self.value < other.value  
  8.  def __eq__(self, other):  
  9.   return self.value == other.value  
  10. print(Number(20) > Number(3))  
  11. print(Number(1) < Number(5))  
  12. print(Number(15) >= Number(15))  
  13. print(Number(10) <= Number(2)) 

這到底如何起作用的?total_ordering 裝飾器用于簡化為我們的類實例實現排序的過程。只需要定義__lt__ 和__eq__,這是最低的要求,裝飾器將映射剩余的操作——它為我們填補了空白。

( 譯注: 原作者的文章分為兩篇,為了方便讀者們閱讀,我特將它們整合在一起,以下便是第二篇的內容。)

10、使用slice函數命名切片

使用大量硬編碼的索引值會很快搞亂維護性和可讀性。一種做法是對所有索引值使用常量,但是我們可以做得更好:

  1. # ID   First Name   Last Name  
  2. line_record = "2        John         Smith"  
  3. ID = slice(0, 8)  
  4. FIRST_NAME = slice(9, 21)  
  5. LAST_NAME = slice(22, 27)  
  6. name = f"{line_record[FIRST_NAME].strip()} {line_record[LAST_NAME].strip()}"  
  7. name == "John Smith" 

在此例中,我們可以避免神秘的索引,方法是先使用 slice 函數命名它們,然后再使用它們。你還可以通過 .start、.stop和 .stop 屬性,來了解 slice 對象的更多信息。

11、在運行時提示用戶輸入密碼

許多命令行工具或腳本需要用戶名和密碼才能操作。因此,如果你碰巧寫了這樣的程序,你可能會發現 getpass 模塊很有用:

  1. import getpass  
  2. user = getpass.getuser()  
  3. password = getpass.getpass()  
  4. # Do Stuff... 

這個非常簡單的包通過提取當前用戶的登錄名,可以提示用戶輸入密碼。但是須注意,并非每個系統都支持隱藏密碼。Python 會嘗試警告你,因此切記在命令行中閱讀警告信息。

12、查找單詞/字符串的相近匹配

現在,關于 Python 標準庫中一些晦澀難懂的特性。如果你發現自己需要使用Levenshtein distance 【2】之類的東西,來查找某些輸入字符串的相似單詞,那么 Python 的 difflib 會為你提供支持。

  1. import difflib  
  2. difflib.get_close_matches( appel , [ ape ,  apple ,  peach ,  puppy ], n=2 
  3. # returns [ apple ,  ape ] 

difflib.get_close_matches 會查找最佳的“足夠好”的匹配。在這里,第一個參數與第二個參數匹配。我們還可以提供可選參數 n ,該參數指定要返回的最多匹配結果。另一個可選的關鍵字參數 cutoff (默認值為 0.6),可以設置字符串匹配得分的閾值。

13、使用IP地址

如果你必須使用 Python 做網絡開發,你可能會發現 ipaddress 模塊非常有用。一種場景是從 CIDR(無類別域間路由 Classless Inter-Domain Routing)生成一系列 IP 地址:

  1. import ipaddress  
  2. net = ipaddress.ip_network( 74.125.227.0/29 )  # Works for IPv6 too  
  3. # IPv4Network( 74.125.227.0/29 )  
  4. for addr in net:  
  5.     print(addr)  
  6. # 74.125.227.0  
  7. # 74.125.227.1  
  8. # 74.125.227.2  
  9. # 74.125.227.3  
  10. # ... 

另一個不錯的功能是檢查 IP 地址的網絡成員資格:

  1. ip = ipaddress.ip_address("74.125.227.3")  
  2. ip in net  
  3. # True  
  4. ip = ipaddress.ip_address("74.125.227.12")  
  5. ip in net  
  6. # False 

還有很多有趣的功能,在這里【3】可以找到,我不再贅述。但是請注意,ipaddress 模塊和其它與網絡相關的模塊之間只有有限的互通性。例如,你不能將 IPv4Network 實例當成地址字符串——需要先使用 str 轉換它們。

14、在Shell中調試程序崩潰

如果你是一個拒絕使用 IDE,并在 Vim 或 Emacs 中進行編碼的人,那么你可能會遇到這樣的情況:擁有在 IDE 中那樣的調試器會很有用。

你知道嗎?你有一個——只要用python3.8 -i 運行你的程序——一旦你的程序終止了, -i 會啟動交互式 shell,在那你可以查看所有的變量和調用函數。整潔,但是使用實際的調試器(pdb )會如何呢?讓我們用以下程序(script.py ):

  1. def func():  
  2.     return 0 / 0  
  3. func() 

并使用python3.8 -i script.py運行腳本:

  1. # Script crashes...  
  2. Traceback (most recent call last):  
  3.   File "script.py", line 4, in <module>  
  4.     func()  
  5.   File "script.py", line 2, in func  
  6.     return 0 / 0  
  7. ZeroDivisionError: division by zero  
  8. >>> import pdb  
  9. >>> pdb.pm()  # Post-mortem debugger  
  10. > script.py(2)func()  
  11. -> return 0 / 0  
  12. (Pdb) 

我們看到了崩潰的地方,現在讓我們設置一個斷點:

  1. def func():  
  2.     breakpoint()  # import pdb; pdb.set_trace()  
  3.     return 0 / 0  
  4. func() 

現在再次運行它:

  1. script.py(3)func()  
  2. -> return 0 / 0  
  3. (Pdb)  # we start here  
  4. (Pdb) step  
  5. ZeroDivisionError: division by zero  
  6. > script.py(3)func()  
  7. -> return 0 / 0  
  8. (Pdb) 

大多數時候,打印語句和錯誤信息就足以進行調試,但是有時候,你需要四處摸索,以了解程序內部正在發生的事情。在這些情況下,你可以設置斷點,然后程序執行時將在斷點處停下,你可以檢查程序,例如列出函數參數、表達式求值、列出變量、或如上所示僅作單步執行。

pdb 是功能齊全的 Python shell,理論上你可以執行任何東西,但是你還需要一些調試命令,可在此處【4】找到。

15、在一個類中定義多個構造函數

函數重載是編程語言(不含 Python)中非常常見的功能。即使你不能重載正常的函數,你仍然可以使用類方法重載構造函數:

  1. import datetime  
  2. class Date:  
  3.     def __init__(self, year, month, day):  
  4.         self.year = year  
  5.         self.month = month  
  6.         self.day = day  
  7.     @classmethod  
  8.     def today(cls):  
  9.         t = datetime.datetime.now()  
  10.         return cls(t.year, t.month, t.day)  
  11. d = Date.today()  
  12. print(f"{d.day}/{d.month}/{d.year}")  
  13. # 14/9/2019 

你可能傾向于將替代構造函數的所有邏輯放入__init__,并使用*args 、**kwargs 和一堆 if 語句,而不是使用類方法來解決。那可能行得通,但是卻變得難以閱讀和維護。

因此,我建議將很少的邏輯放入__init__,并在單獨的方法/構造函數中執行所有操作。這樣,對于類的維護者和用戶而言,得到的都是干凈的代碼。

16、使用裝飾器緩存函數調用

你是否曾經編寫過一種函數,它執行昂貴的 I/O 操作或一些相當慢的遞歸,而且該函數可能會受益于對其結果進行緩存(存儲)?如果你有,那么有簡單的解決方案,即使用 functools 的lru_cache :

  1. from functools import lru_cache  
  2. import requests  
  3. @lru_cache(maxsize=32 
  4. def get_with_cache(url):  
  5.     try:  
  6.         r = requests.get(url)  
  7.         return r.text 
  8.      except:  
  9.         return "Not Found"  
  10. for url in ["https://google.com/",  
  11.             "https://martinheinz.dev/",  
  12.             "https://reddit.com/",  
  13.             "https://google.com/",  
  14.             "https://dev.to/martinheinz",  
  15.             "https://google.com/"]:  
  16.     get_with_cache(url)  
  17. print(get_with_cache.cache_info())  
  18. # CacheInfo(hits=2misses=4maxsize=32currsize=4

在此例中,我們用了可緩存的 GET 請求(最多 32 個緩存結果)。你還可以看到,我們可以使用 cache_info 方法檢查函數的緩存信息。裝飾器還提供了 clear_cache 方法,用于使緩存結果無效。

我還想指出,此函數不應與具有副作用的函數一起使用,或與每次調用都創建可變對象的函數一起使用。

17、在可迭代對象中查找最頻繁出現的元素

在列表中查找最常見的元素是非常常見的任務,你可以使用 for 循環和字典(map),但是這沒必要,因為 collections 模塊中有 Counter 類:

  1. from collections import Counter  
  2. cheese = ["gouda", "brie", "feta", "cream cheese", "feta", "cheddar",  
  3.           "parmesan", "parmesan", "cheddar", "mozzarella", "cheddar", "gouda",  
  4.           "parmesan", "camembert", "emmental", "camembert", "parmesan"]  
  5. cheese_count = Counter(cheese)  
  6. print(cheese_count.most_common(3))  
  7. # Prints: [( parmesan , 4), ( cheddar , 3), ( gouda , 2)] 

實際上,Counter 只是一個字典,將元素與出現次數映射起來,因此你可以將其用作普通字典:

pythonprint(cheese_count["mozzarella"])¨K40Kcheese_count["mozzarella"] += 1print(cheese_count["mozzarella"])¨K41K

除此之外,你還可以使用 update(more_words) 方法輕松添加更多元素。Counter 的另一個很酷的特性是你可以使用數學運算(加法和減法)來組合和減去 Counter 的實例。

原文地址:https://mp.weixin.qq.com/s/Cvb35n2ahsR-38k38u9jyQ

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国内精品久久久久久 | www.久久精品 | www久久久 | 中文字幕乱码一区二区三区 | 欧美男人的天堂 | 精品久久久久久久久久久久 | 欧美一级特黄在线观看 | 国产欧美精品一区二区三区四区 | a一级免费视频 | 欧美精品成人一区二区三区四区 | 99中文字幕| 99精品免费 | 一区二区三区高清不卡 | 亚洲国产精品一区二区久久,亚洲午夜 | 男女免费观看在线爽爽爽视频 | 中文字幕视频 | 九九精品视频在线观看 | www.888www看片| 国产黄色在线观看 | 日韩av中文字幕在线播放 | 亚洲专区国产精品 | 色播久久| 日韩免费视频 | 一区二区三区视频 | 亚洲人人| 操操操av| 欧美精品一区二区三区蜜桃视频 | 在线欧美亚洲 | 在线观看欧美日韩 | 在线观看国产中文字幕 | 国产福利视频在线观看 | 在线欧美 | 成人精品一区亚洲午夜久久久 | 蜜桃一区二区 | 久久久国际精品 | 欧美日韩视频在线第一区 | 亚洲欧美精品一区二区三区 | 欧美成在线观看 | 欧美一级片| 免费观看一级毛片 | 亚洲精品日本 |