摘要:流暢的中有很多奇技淫巧,整本書都在強調如何最大限度地利用標準庫。常見的扁平序列包括,,等。數組支持所有跟可變序列有關的操作,包括和。和用于指定列表的區間,默認是使用整個列表。但是元組的賦值不被允許,當異發生時
流暢的python中有很多奇技淫巧,整本書都在強調如何最大限度地利用Python 標準庫。介紹了很多python的不常用的數據類型、操作、庫等,對于入門python后想要提升對python的認識應該有幫助。目前讀一遍記錄了一些有共鳴的操作:
Python內置序列類型的主要分類:按可存放的元素類型分為:容器序列和扁平序列
容器序列,就是什么都能作為元素往里放,包括另一個序列。需要注意的是,如果元素是序列類型,那么存放的往往是引用,需要小心。
常見的容器序列包括:list,tuple,array.array,collections.deque等。
扁平序列,存放的都是原子級元素,此時存放的是值而不會是引用。
常見的扁平序列包括:str,bytes,bytearray, memoryview, array.array等。
按序列能否被修改分為:可變序列與不可變序列
可變序列:可以進行增、刪、改等操作的序列,包括list, bytearray, array.array, collections.deque, memoryview等。
不可變序列:不可進行上述操作的序列,包括tuple, str, bytes等。
字典的變種標準庫里collections模塊中提供了很多與字典類型相似的變種。
OrderDict: 這個類型在添加鍵的時候,會保存順序,因此鍵的迭代順序總是一致的
ChainMap: 該類型可以容納數個不同的映射對像,在進行鍵的查找時,這些對象會被當做一個整體逐個查找,直到鍵被找到為止
Counter: 這個映射類型會給鍵準備一個整數技術器,每次更行一個鍵的時候都會增加這個計數器,所以這個類型可以用來給散列表對象計數,或者當成多重集來用。
UserDict: 這個類其實就是把標準的dict用Python又寫了一遍。一般用來給程序員想要通過繼承dict創建自己的dict時,代替dict使用的。主要是因為直接繼承原生dict會出現bug。
defaultdict:處理找不到的鍵的一個選擇
當某個鍵不在映射里, 我們也希望也能得到一個默認值. 這就是 defaultdict , 它是 dict 的子類, 并實現了 missing 方法.
鍵必須是可散列的: 一個可散列的對象必須滿足以下要求。 (1) 支持 hash() 函數,并且通過 __hash__() 方法所得到的散列值是不變的。 (2) 支持通過 __eq__() 方法來檢測相等性。 (3) 若 a == b 為真,則 hash(a) == hash(b) 也為真。 所有由用戶自定義的對象默認都是可散列的,因為它們的散列值由 id() 來獲取,而 且它們都是不相等的。 字典在內存上開銷很大(用內存換效率)。 元組取代字典就能節省空間的原因有兩個: (1) 避免了散列表所耗費的空間, (2) 無需把記錄中字段的名字在每個元素里都存一遍。 鍵的查詢很快 鍵的次序取決于添加順序 往字典里添加新鍵可能會改變已有鍵的順序set的實現以及導致的結果
結合的元素必須是可散列的 集合和消耗內存 可以很高效的判斷元素是否存在于某個集合 元素的次序取決于被添加到集合里的順序 往集合里添加元素,可能會改變集合里已有的元素次序collections.namedtuple 可以用來構建一個帶字段名的元組和一個有名字的類
創建一個具名元組需要兩個參數,一個是類名,另一個是類的各個字段的名字。后者
可以是由數個字符串組成的可迭代對象,或者是由空格分隔開的字段名組成的字符串。
>>> from collections import namedtuple >>> City = namedtuple("City", "name country population coordinates") >>> tokyo = City("Tokyo", "JP", 36.933, (35.689722, 139.691667)) >>> tokyo City(name="Tokyo", country="JP", population=36.933, coordinates=(35.689722, 139.691667)) >>> tokyo.population 36.933 >>> tokyo.coordinates (35.689722, 139.691667) >>> tokyo[1] "JP" >>> City = namedtuple("City_Name", "name country population coordinates") >>> tokyo = City("Tokyo", "JP", 36.933, (35.689722, 139.691667)) >>> tokyo City_Name(name="Tokyo", country="JP", population=36.933, coordinates=(35.689722, 139.691667))當列表不是首選時
如果我們需要一個只包含數字的列表,那么 array.array 比 list 更高效。數組支持所
有跟可變序列有關的操作,包括 .pop、.insert 和 .extend。另外,數組還提供從文件
讀取和存入文件的更快的方法,如 .frombytes 和 .tofile。
set 專為檢查元素是否存在做過優化
memoryview 是一個內置類,它能讓用戶在不復制內容的情況下操作同一個數組的不同切
片。
使用NumPy和SciPy提供的高階數組和矩陣操作
使用雙向隊列和其他形式的隊列(collections.deque 雙向隊列類、queue類中的 Queue、LifoQueue和PriorityQueue、multiprocessing. Queue、heapq可以把可變序列當作堆隊列或者優先隊列來使用)
Python 格式化輸出在進行格式化輸出時,%r 與 %s 的區別就好比 repr() 函數處理對象與 str() 函數處理對象的差別。
%s -> str(),比較智能;
%r -> repr(),處理較為簡單和直接; 處理一些簡單對象時,二者幾乎沒有差別.
本文重點列舉一些二者的差異化用法:
處理字符串時
>> s = "world" >> print("hello %s"%s) hello world >> print("hello %r"%s) hello "world" >> str(s) "world" >> repr(s) ""world"" 2. datetime 庫中的 datetime 對象 >> from datetime import datetime >> timeinfo = datetime.today() >> timeinfo datetime.datetime(2016, 6, 7, 21, 17, 34, 925488) >> type(timeinfo) datetime.datetime >> repr(timeinfo) "datetime.datetime(2016, 6, 7, 21, 17, 34, 925488)" >> str(timeinfo) "2016-06-07 21:17:34.925488"反匯編函數 python opcode
Python dis 模塊支持對Python代碼進行反匯編, 生成字節碼指令。
In[1]: def test(): ... x = 1 ... if x < 3: ... return "yes" ... else: ... return "no" In[2]: dis.dis(test) 2 0 LOAD_CONST 1 (1) 3 STORE_FAST 0 (x) 3 6 LOAD_FAST 0 (x) 9 LOAD_CONST 2 (3) 12 COMPARE_OP 0 (<) 15 POP_JUMP_IF_FALSE 22 4 18 LOAD_CONST 3 ("yes") 21 RETURN_VALUE 6 >> 22 LOAD_CONST 4 ("no") 25 RETURN_VALUE 26 LOAD_CONST 0 (None) 29 RETURN_VALUE >>> def add(a, b = 0): ... return a + b ... >>> >>> dis.dis(add) 2 0 LOAD_FAST 0 (a) 2 LOAD_FAST 1 (b) 4 BINARY_ADD 6 RETURN_VALUE >>>
class memoryview(obj)是python的內置類,如果要用memoryview 去引用一個object, 那么這個object 必須支持buffer protocol, python3 中原生(built-in) 支持buffer protocol的obj有bytes和bytearray,memoryview可以使用不同的方式讀取和操作同一塊內存,并且原有的內存字節不會隨意移動。類似于C中的強轉,好處是不會有內存拷貝。
例如,使用memoryview修改一個短整型有符號整數數組的數據。
from array import array from random import random numbers = array("h", [-2, -1, 0, 1, 2]) #signed short memv = memoryview(numbers) #5個短整型有符號整數的數組創建一個memoryview print (len(memv)) #打印長度 print (memv.tolist()) #轉換成列表形式 memv_oct = memv.cast("B") #內存共享 轉換成無符號字符類型 print (memv_oct.tolist()) memv_oct[5] = 4 #把位置5的字節賦值成4 print (numbers) #因為我們把占 2 個字節的整數的高位字節改成了 4,所以這個有符號整數的值就變成了 1024 輸出如下: 5 #數組長度 [-2, -1, 0, 1, 2] #列表形式顯示 [254, 255, 255, 255, 0, 0, 1, 0, 2, 0]#長度擴大一倍 轉換為無符號字符類型 array("h", [-2, -1, 1024, 1, 2]) #原來的數組被修改
bytearray是可變(mutable)的字節序列,相對于Python2中的str,但str是不可變(immutable)的。
在Python3中由于str默認是unicode編碼,所以只有通過bytearray才能按字節訪問。
下面兩種行為的對比:
簡單點就是,str和bytearray的切片操作會產生新的切片str和bytearry并拷貝數據,使用memoryview之后不會。
python2中的例子
>> a = "aaaaaa" >> b = a[:2] # 會產生新的字符串 >> a = bytearray("aaaaaa") >> b = a[:2] # 會產生新的bytearray >> b[:2] = "bb" # 對b的改動不影響a >> a bytearray(b"aaaaaa") >> b bytearray(b"bb")
>> a = "aaaaaa" >> ma = memoryview(a) >> ma.readonly # 只讀的memoryview True >> mb = ma[:2] # 不會產生新的字符串 >> a = bytearray("aaaaaa") >> ma = memoryview(a) >> ma.readonly # 可寫的memoryview False >> mb = ma[:2] # 不會會產生新的bytearray >> mb[:2] = "bb" # 對mb的改動就是對ma的改動 >> mb.tobytes() "bb" >> ma.tobytes() "bbaaaa"
Python 中有各種各樣可調用的類型,因此判斷置的 callable() 函數:
>>> abs, str, 13 (, , 13) >>> [callable(obj) for obj in (abs, str, 13)] [True, True, False]
>>> import random >>> a=range(10) >>> random.shuffle(a) >>> a [1, 0, 8, 5, 6, 7, 9, 3, 2, 4] >>> random.shuffle(a) >>> a [7, 5, 6, 2, 1, 8, 9, 0, 3, 4]vim常用快捷
0 → 數字零,到行頭
$ → 到本行行尾
a → 在光標后插入
o → 在當前行后插入一個新行
O → 在當前行前插入一個新行
cw → 替換從光標所在位置后到一個單詞結尾的字符
. → (小數點) 可以重復上一次的命令
NG → 到第 N 行 (注意命令中的G是大寫的,另我一般使用 : N 到第N行,如 :137 到第137行)
gg → 到第一行。(相當于1G,或 :1)
G → 到最后一行。
在 Insert 模式下,你可以輸入一個詞的開頭,然后按
Math Function Description abs() Returns absolute value of a number divmod() Returns quotient and remainder of integer division max() Returns the largest of the given arguments or items in an iterable min() Returns the smallest of the given arguments or items in an iterable pow() Raises a number to a power round() Rounds a floating-point value sum() Sums the items of an iterable Type Conversion Function Description ascii() Returns a string containing a printable representation of an object bin() Converts an integer to a binary string bool() Converts an argument to a Boolean value chr() Returns string representation of character given by integer argument complex() Returns a complex number constructed from arguments float() Returns a floating-point object constructed from a number or string hex() Converts an integer to a hexadecimal string int() Returns an integer object constructed from a number or string oct() Converts an integer to an octal string ord() Returns integer representation of a character repr() Returns a string containing a printable representation of an object str() Returns a string version of an object type() Returns the type of an object or creates a new type object Iterables and Iterators Function Description all() Returns True if all elements of an iterable are true any() Returns True if any elements of an iterable are true enumerate() Returns a list of tuples containing indices and values from an iterable filter() Filters elements from an iterable iter() Returns an iterator object len() Returns the length of an object map() Applies a function to every item of an iterable next() Retrieves the next item from an iterator range() Generates a range of integer values reversed() Returns a reverse iterator slice() Returns a slice object sorted() Returns a sorted list from an iterable zip() Creates an iterator that aggregates elements from iterables Composite Data Type Function Description bytearray() Creates and returns an object of the bytearray class bytes() Creates and returns a bytes object (similar to bytearray, but immutable) dict() Creates a dict object frozenset() Creates a frozenset object list() Constructs a list object object() Returns a new featureless object set() Creates a set object tuple() Creates a tuple object Classes, Attributes, and Inheritance Function Description classmethod() Returns a class method for a function delattr() Deletes an attribute from an object getattr() Returns the value of a named attribute of an object hasattr() Returns True if an object has a given attribute isinstance() Determines whether an object is an instance of a given class issubclass() Determines whether a class is a subclass of a given class property() Returns a property value of a class setattr() Sets the value of a named attribute of an object super() Returns a proxy object that delegates method calls to a parent or sibling class Input/Output Function Description format() Converts a value to a formatted representation input() Reads input from the console open() Opens a file and returns a file object print() Prints to a text stream or the console Variables, References, and Scope Function Description dir() Returns a list of names in current local scope or a list of object attributes globals() Returns a dictionary representing the current global symbol table id() Returns the identity of an object locals() Updates and returns a dictionary representing current local symbol table vars() Returns __dict__ attribute for a module, class, or object Miscellaneous Function Description callable() Returns True if object appears callable compile() Compiles source into a code or AST object eval() Evaluates a Python expression exec() Implements dynamic execution of Python code hash() Returns the hash value of an object help() Invokes the built-in help system memoryview() Returns a memory view object staticmethod() Returns a static method for a function __import__() Invoked by the import statement跟運算符無關的特殊方法
類別 方法名 字符串 / 字節序列表示形式 __repr__、__str__、__format__、__bytes__ 數值轉換 __abs__、__bool__、__complex__、__int__、__float__、__hash__、__index__ 集合模擬 __len__、__getitem__、__setitem__、__delitem__、__contains__ 迭代枚舉 __iter__、__reversed__、__next__ 可調用模擬 __call__ 上下文管理 __enter__、__exit__ 實例創建和銷毀 __new__、__init__、__del__ 屬性管理 __getattr__、__getattribute__、__setattr__、__delattr__、__dir__ 屬性描述符 __get__、__set__、__delete__ 跟類相關的服務 __prepare__、__instancecheck__、__subclasscheck__Bisect模塊管理有序的序列
bisect.bisect_left(a,x, lo=0, hi=len(a)) : 查找在有序列表 a 中插入 x 的index。lo 和 hi 用于指定列表的區間,默認是使用整個列表。如果 x 已經存在,在其左邊插入。返回值為 index。 bisect.bisect_right(a,x, lo=0, hi=len(a)) bisect.bisect(a, x,lo=0, hi=len(a)) : 這2個函數和 bisect_left 類似,但如果 x 已經存在,在其右邊插入。 bisect.insort_left(a,x, lo=0, hi=len(a)) : 在有序列表 a 中插入 x。和 a.insert(bisect.bisect_left(a,x, lo, hi), x) 的效果相同。 bisect.insort_right(a,x, lo=0, hi=len(a)) bisect.insort(a, x,lo=0, hi=len(a)) : 和 insort_left 類似,但如果 x 已經存在,在其右邊插入。 Bisect 模塊提供的函數可以分兩類: bisect* 只用于查找 index, 不進行實際的插入;而 insort* 則用于實際插入。當list不是最優選擇時,dict是python的核心類型,但它是以空間換時間的結果,比較占內存,tuple是dict結構比較好的替代,set用來做是否包含和去重很合適。
from array import array from random import random floats = array("d", (random() for i in range(10**7))) fp = open("floats.bin", "wb") floats.tofile(fp) fp.close() floats2 = array("d") fp = open("floats.bin", "rb") floats2.fromfile(fp, 10**7) fp.close() floats2 == floatsPython_內置四種隊列
from queue import Queue #LILO隊列 q = Queue() #創建隊列對象 q.put(0) #在隊列尾部插入元素 q.put(1) q.put(2) print("LILO隊列",q.queue) #查看隊列中的所有元素 print(q.get()) #返回并刪除隊列頭部元素 print(q.queue) from queue import LifoQueue #LIFO隊列 lifoQueue = LifoQueue() lifoQueue.put(1) lifoQueue.put(2) lifoQueue.put(3) print("LIFO隊列",lifoQueue.queue) lifoQueue.get() #返回并刪除隊列尾部元素 lifoQueue.get() print(lifoQueue.queue) from queue import PriorityQueue #優先隊列 priorityQueue = PriorityQueue() #創建優先隊列對象 priorityQueue.put(3) #插入元素 priorityQueue.put(78) #插入元素 priorityQueue.put(100) #插入元素 print(priorityQueue.queue) #查看優先級隊列中的所有元素 priorityQueue.put(1) #插入元素 priorityQueue.put(2) #插入元素 print("優先級隊列:",priorityQueue.queue) #查看優先級隊列中的所有元素 priorityQueue.get() #返回并刪除優先級最低的元素 print("刪除后剩余元素",priorityQueue.queue) priorityQueue.get() #返回并刪除優先級最低的元素 print("刪除后剩余元素",priorityQueue.queue) #刪除后剩余元素 priorityQueue.get() #返回并刪除優先級最低的元素 print("刪除后剩余元素",priorityQueue.queue) #刪除后剩余元素 priorityQueue.get() #返回并刪除優先級最低的元素 print("刪除后剩余元素",priorityQueue.queue) #刪除后剩余元素 priorityQueue.get() #返回并刪除優先級最低的元素 print("全部被刪除后:",priorityQueue.queue) #查看優先級隊列中的所有元素 from collections import deque #雙端隊列 dequeQueue = deque(["Eric","John","Smith"]) print(dequeQueue) dequeQueue.append("Tom") #在右側插入新元素 dequeQueue.appendleft("Terry") #在左側插入新元素 print(dequeQueue) dequeQueue.rotate(2) #循環右移2次 print("循環右移2次后的隊列",dequeQueue) dequeQueue.popleft() #返回并刪除隊列最左端元素 print("刪除最左端元素后的隊列:",dequeQueue) dequeQueue.pop() #返回并刪除隊列最右端元素 print("刪除最右端元素后的隊列:",dequeQueue) 以上隊列在多線程中可以使用的且線程安全,但在多進程中都不能用于通信。在多進程中,需要這樣使用: from multiprocessing import Process, Queue myqueue = Queue(100) ## 參考 https://blog.csdn.net/sinat_38682860/article/details/80392493 https://www.cnblogs.com/cmnz/p/6936181.html關鍵字
from keyword import kwlist print(kwlist)builtins模塊
import builtins dir(builtins)Python locals() 的陷阱
https://segmentfault.com/a/1190000012724861 def test(): globals()["a2"] = 4 test() print a2 # 輸出 4 def aaaa(): print locals() for i in ["a", "b", "c"]: locals()[i] = 1 print locals() print a # 錯誤:NameError: global name "a" is not defined aaaa()
動態地進行變量賦值時,locals() 看到的, 的確是函數的局部命名空間的內容, 但是它本身不能代表局部命名空間, 這就好像一個代理, 它收集了A, B, C的東西, 展示給我看, 但是我卻不能簡單的通過改變這個代理, 來改變A, B, C真正擁有的東西!
這也就是為什么, 當我們通過locals()[i] = 1的方式去動態賦值時, print a卻觸發了NameError異常, 而相反的, globals()確實真正的全局命名空間,
所以一般會說locals() 只讀, globals() 可讀可寫。
對于一般不可變類型的變量來說這兩個方法沒啥區別,但對于可變類型如list(列表),dict(字典)就有區別了,x += y 就地改變了list的值,而x = x + y創建了一個新的list并重新將x綁定上去,通過id(x)就可以看出。
l = l + [3, 4, 5] 這種背后就是BINARY_ADD l += [3, 4, 5] 這種背后就是INPLACE_ADD
+=實際上應該能算是一個加強版的+, 因為它比+多了一個寫回本身的功能.不過是否能夠寫回本身, 還是得看對象自身是否支持, 也就是說是否具備Py_NotImplemented標識, 是否支持sq_inplace_concat, 如果具備, 才能實現, 否則, 也就是和 + 效果一樣而已.
不僅僅是這些,當混合使用可變類型和不可變類型的時候,你會有更加驚奇的發現:
>>> t = ([],) >>> t[0] += [2, 3] Traceback (most recent call last): File "", line 1, in ? TypeError: object doesn"t support item assignment >>> t ([2, 3],)
明顯的,元組不支持對其中元素的賦值——但是在對他使用+=后,元組里的list確實改變了!原因依然是+=就地改變list的值。但是元組的賦值不被允許,當異發生時,元組中的list已經被就地改變了。
這就是一個我個人覺得非常致命的陷阱。
解決方法:干脆避免使用+=,或者僅僅在整數時使用它。
>>> a=(1) # 錯誤姿勢 >>> type(a)Python的list循環遍歷中,刪除數據的正確方法>>> a=(1,) # 正確姿勢 >>> type(a)
通用的解決方案:
num_list = [1, 2, 3, 4, 5, 2, 2, 4] 1. 倒序循環遍歷 for i in range(len(num_list) - 1, -1, -1): # 講究 if num_list[i] == 2: num_list.pop(i) print(num_list) 2. 遍歷拷貝的list,操作原始的list。對于過大的list,拷貝后可能很占內存,可以用倒序遍歷的方法來實現。 for item in num_list[:]: # 保證可以把num_list從頭遍歷到尾 if item == 2: num_list.remove(item) # 從頭刪除遇到的第一個item print(num_list) 3. 對原來的列表做過濾,生成一個新的列表(假設determine(x)為判斷條件的函數): list = [x for x in list if not determine(x)] 4. 在原來列表上做切片,僅保留需要的元素 list[:] = [x for x in list if not determine(x)] 5. python2.x ifilterfalse()方法 from itertools import ifilterfalse() list[:] = ifilterfalse(determine, list) 6. Python3 filterfalse()方法 from itertools import filterfalse list[:] = filterfalse(determine, list) 方法5,6對列表的修改會反應到其他對此列表的引用上。作用域解析是基于LEGB規則,分別是Local、Enclosing、Global、Built-in 函數內定義的局部變量必須global申明才能使用全局變量
def local_var_err(): b += [3] # UnboundLocalError: local variable "b" referenced before assignment b = b + [2] # UnboundLocalError: local variable "b" referenced before assignment不遍歷情況下迭代器與生成器的性能比較
In [109]: %timeit -n100 a = (i for i in range(100000)) 100 loops, best of 3: 659 μs per loop In [110]: %timeit -n100 b = [i for i in range(100000)] 100 loops, best of 3: 2.68 ms per loop遍歷情況下迭代器與生成器的性能比較
In [112]: %timeit -n100 for x in (i for i in range(100000)):pass 100 loops, best of 3: 4.23 ms per loop In [113]: %timeit -n100 for x in [i for i in range(100000)]:pass 100 loops, best of 3: 3.49 ms per loop
空間換時間
盡量使用局部變量# -*- coding:utf-8 -*- import timeit test_dict = {} class dome(object): def test_class(self): num = 100 self.test_dict = {} # 為了公平,每次執行都同樣初始化新的 {} for i in range(num): self.test_dict[i] = i def test_local(self): num = 100 test_dict = {} # 為了公平,每次執行都同樣初始化新的 {} for i in range(num): test_dict[i] = i self.test_dict = test_dict def test_global(self): num = 100 global test_dict test_dict = {} # 為了公平,每次執行都同樣初始化新的 {} for i in range(num): test_dict[i] = i s = dome() print(timeit.timeit(stmt=s.test_class)) # 9.75976037823 print(timeit.timeit(stmt=s.test_local)) # 7.17526431985 print(timeit.timeit(stmt=s.test_global)) # 7.57540534177 """ 1. 訪問局部變量速度要快很多 2. 循環之外能做的事不要放在循環內 在一些會頻繁操作 類/實例屬性 的情況下,應該是先把 屬性 取出來存到 局部變量,然后用 局部變量 來完成操作。最后視情況把變動更新到 屬性 上。 """拼接字符串列表時使用join
a=list(str(range(1000))) In [126]: %%timeit s="" for x in a: s+=x .....: 1000 loops, best of 3: 304 μs per loop In [127]: %%timeit .....: s="".join(a) .....: 10000 loops, best of 3: 59.3 μs per loop 參考博客 https://blog.csdn.net/xdhstc/article/details/51719892if is True 對比 if == True,列表推導。
# -*- coding:utf-8 -*- import timeit def test_1(): a = [True] * 100 s = [] for i in a: if i == True: s.append(i) return s def test_2(): a = [True] * 100 return [i for i in a if i is True] def test_3(): a = [True] * 100 return [i for i in a if i == True] def test_4(): a = [True] * 100 return [i for i in a if i] print(timeit.timeit(stmt=test_1)) # 11.5888194259 print(timeit.timeit(stmt=test_2)) # 6.00562291202 print(timeit.timeit(stmt=test_3)) # 7.15504198257 print(timeit.timeit(stmt=test_4)) # 4.29275713242使用**而不是pow
In [145]: %timeit -n100000 c = pow(2,20) 100000 loops, best of 3: 89.3 ns per loop In [146]: %timeit -n100000 c = 2**20 100000 loops, best of 3: 22.2 ns per loop帶有條件判斷的嵌套for循環時盡量分析條件減少循環次數
# -*- coding:utf-8 -*- import timeit def test1(): s = [] for z in range(10): for y in range(100): for x in range(1000): if x > 100 and y > 50 and z > 5: return s s.append((x, y, z)) def test2(): s = [] for x in range(1000): for y in range(100): for z in range(10): if x > 100 and y > 50 and z > 5: return s s.append((x, y, z)) print(timeit.timeit(stmt=test1, number=100)) # 14.1777687741 print(timeit.timeit(stmt=test2, number=100)) # 2.03417086749 print(sorted(test1()) == sorted(test2())) # False print(len(test1())) # 651101 print(len(test2())) # 101516
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/42472.html
摘要:于是打算看一下流暢的。第一章是講數據模型,主要是的魔術方法特殊方法,它們以雙下劃線開頭和結束,能讓我們自己寫的類擁有類似內置對象那樣的屬性和方法。第三個出場的的是,把對象用字符串的形式表示出來。第六個是,用于實現自己定義的布爾值。 接觸 Python 有一段時間了,但是到現在也沒怎么用 Python 寫過一些有用的東西。基礎雖然還行,但更深入的就不怎么了解了。于是打算看一下《流暢的 P...
摘要:不同編碼器編碼的相同的字符,最終的字節大小可能會不同。對于和,是由于對應編碼不能處理字符串字節導致的。在另外兩個規范化形式和的首字母縮略詞中,字母表示兼容性。最后是雙模,同一函數能接受字符串和字節進行操作。 對于字符串,我們接觸得挺多的。而編碼問題,也不時令人頭疼的。 由于一開始接觸的就是 Python3,所以一些在 Python2 上的編碼上的坑我沒遇到,甚至在 Python3 上都...
摘要:今天深入接觸了中的函數,發現函數比我想象的要高深。介紹的幾個高階函數有內置的和函數,模塊中的。可調用對象即能被調用運算符應用的對象,可使用內置的函數檢測。函數的三個屬性和放置了函數對象參數的一些信息。 今天深入接觸了 Python 中的函數,發現函數比我想象的要高深。 Python 中萬物皆對象,這一章就介紹了函數作為對象的一些屬性。首先是測試所有對象共有的屬性__doc__,可以看到...
摘要:第一章數據類型隱式方法利用快速生成類方法方法通過下標找元素自動支持切片操作可迭代方法與如果是一個自定義類的對象,那么會自己去調用其中由你實現的方法。若返回,則會返回否則返回。一個對象沒有函數,解釋器會用作為替代。 第一章 python數據類型 1 隱式方法 利用collections.namedtuple 快速生成類 import collections Card = collec...
摘要:第一章數據類型隱式方法利用快速生成字典方法方法通過下標找元素自動支持切片操作可迭代方法與如果是一個自定義類的對象,那么會自己去調用其中由你實現的方法。若返回,則會返回否則返回。一個對象沒有函數,解釋器會用作為替代。 第一章 python數據類型 1 隱式方法 利用collections.namedtuple 快速生成字典 import collections Card = coll...
閱讀 3061·2021-11-23 09:51
閱讀 1040·2021-09-02 15:21
閱讀 3005·2019-08-30 13:56
閱讀 1829·2019-08-29 14:12
閱讀 708·2019-08-29 13:53
閱讀 1664·2019-08-29 11:32
閱讀 1325·2019-08-29 11:25
閱讀 1493·2019-08-28 17:51