<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          20個Python使用小技巧,建議收藏!

          共 5799字,需瀏覽 12分鐘

           ·

          2022-01-12 13:10


          來源丨知乎-張皓

          1. 易混淆操作

          本節(jié)對一些 Python 易混淆的操作進(jìn)行對比。

          1.1 有放回隨機(jī)采樣和無放回隨機(jī)采樣

          import random
          random.choices(seq, k=1) # 長度為k的list,有放回采樣
          random.sample(seq, k) # 長度為k的list,無放回采樣

          1.2 lambda 函數(shù)的參數(shù)

          func = lambda y: x + y          # x的值在函數(shù)運(yùn)行時被綁定
          func = lambda y, x=x: x + y # x的值在函數(shù)定義時被綁定

          1.3 copy 和 deepcopy

          import copy
          y = copy.copy(x) # 只復(fù)制最頂層
          y = copy.deepcopy(x) # 復(fù)制所有嵌套部分

          復(fù)制和變量別名結(jié)合在一起時,容易混淆:

          a = [1, 2, [3, 4]]

          # Alias.
          b_alias = a
          assert b_alias == a and b_alias is a

          # Shallow copy.
          b_shallow_copy = a[:]
          assert b_shallow_copy == a and b_shallow_copy is not a and b_shallow_copy[2] is a[2]

          # Deep copy.
          import copy
          b_deep_copy = copy.deepcopy(a)
          assert b_deep_copy == a and b_deep_copy is not a and b_deep_copy[2] is not a[2]

          對別名的修改會影響原變量,(淺)復(fù)制中的元素是原列表中元素的別名,而深層復(fù)制是遞歸的進(jìn)行復(fù)制,對深層復(fù)制的修改不影響原變量。

          1.4 == 和 is

          x == y  # 兩引用對象是否有相同值
          x is y # 兩引用是否指向同一對象

          1.5 判斷類型

          type(a) == int      # 忽略面向?qū)ο笤O(shè)計(jì)中的多態(tài)特征
          isinstance(a, int) # 考慮了面向?qū)ο笤O(shè)計(jì)中的多態(tài)特征

          1.6 字符串搜索

          str.find(sub, start=None, end=None); str.rfind(...)     # 如果找不到返回-1
          str.index(sub, start=None, end=None); str.rindex(...) # 如果找不到拋出ValueError異常

          1.7 List 后向索引

          這個只是習(xí)慣問題,前向索引時下標(biāo)從0開始,如果反向索引也想從0開始可以使用~。

          print(a[-1], a[-2], a[-3])
          print(a[~0], a[~1], a[~2])


          2. 常用工具

          2.1 讀寫 CSV 文件

          import csv
          # 無header的讀寫
          with open(name, 'rt', encoding='utf-8', newline='') as f: # newline=''讓Python不將換行統(tǒng)一處理
          for row in csv.reader(f):
          print(row[0], row[1]) # CSV讀到的數(shù)據(jù)都是str類型
          with open(name, mode='wt') as f:
          f_csv = csv.writer(f)
          f_csv.writerow(['symbol', 'change'])

          # 有header的讀寫
          with open(name, mode='rt', newline='') as f:
          for row in csv.DictReader(f):
          print(row['symbol'], row['change'])
          with open(name, mode='wt') as f:
          header = ['symbol', 'change']
          f_csv = csv.DictWriter(f, header)
          f_csv.writeheader()
          f_csv.writerow({'symbol': xx, 'change': xx})

          注意,當(dāng) CSV 文件過大時會報(bào)錯:_csv.Error: field larger than field limit (131072),通過修改上限解決

          import sys
          csv.field_size_limit(sys.maxsize)

          csv 還可以讀以 \t 分割的數(shù)據(jù)

          f = csv.reader(f, delimiter='\t')

          2.2 迭代器工具

          itertools 中定義了很多迭代器工具,例如子序列工具:

          import itertools
          itertools.islice(iterable, start=None, stop, step=None)
          # islice('ABCDEF', 2, None) -> C, D, E, F

          itertools.filterfalse(predicate, iterable) # 過濾掉predicate為False的元素
          # filterfalse(lambda x: x < 5, [1, 4, 6, 4, 1]) -> 6

          itertools.takewhile(predicate, iterable) # 當(dāng)predicate為False時停止迭代
          # takewhile(lambda x: x < 5, [1, 4, 6, 4, 1]) -> 1, 4

          itertools.dropwhile(predicate, iterable) # 當(dāng)predicate為False時開始迭代
          # dropwhile(lambda x: x < 5, [1, 4, 6, 4, 1]) -> 6, 4, 1

          itertools.compress(iterable, selectors) # 根據(jù)selectors每個元素是True或False進(jìn)行選擇
          # compress('ABCDEF', [1, 0, 1, 0, 1, 1]) -> A, C, E, F

          序列排序:

          sorted(iterable, key=None, reverse=False)

          itertools.groupby(iterable, key=None) # 按值分組,iterable需要先被排序
          # groupby(sorted([1, 4, 6, 4, 1])) -> (1, iter1), (4, iter4), (6, iter6)

          itertools.permutations(iterable, r=None) # 排列,返回值是Tuple
          # permutations('ABCD', 2) -> AB, AC, AD, BA, BC, BD, CA, CB, CD, DA, DB, DC

          itertools.combinations(iterable, r=None) # 組合,返回值是Tuple
          itertools.combinations_with_replacement(...)
          # combinations('ABCD', 2) -> AB, AC, AD, BC, BD, CD

          多個序列合并:

          itertools.chain(*iterables)                        # 多個序列直接拼接
          # chain('ABC', 'DEF') -> A, B, C, D, E, F

          import heapq
          heapq.merge(*iterables, key=None, reverse=False) # 多個序列按順序拼接
          # merge('ABF', 'CDE') -> A, B, C, D, E, F

          zip(*iterables) # 當(dāng)最短的序列耗盡時停止,結(jié)果只能被消耗一次
          itertools.zip_longest(*iterables, fillvalue=None) # 當(dāng)最長的序列耗盡時停止,結(jié)果只能被消耗一次

          2.3 計(jì)數(shù)器

          計(jì)數(shù)器可以統(tǒng)計(jì)一個可迭代對象中每個元素出現(xiàn)的次數(shù)。

          import collections
          # 創(chuàng)建
          collections.Counter(iterable)

          # 頻次
          collections.Counter[key] # key出現(xiàn)頻次
          # 返回n個出現(xiàn)頻次最高的元素和其對應(yīng)出現(xiàn)頻次,如果n為None,返回所有元素
          collections.Counter.most_common(n=None)

          # 插入/更新
          collections.Counter.update(iterable)
          counter1 + counter2; counter1 - counter2 # counter加減

          # 檢查兩個字符串的組成元素是否相同
          collections.Counter(list1) == collections.Counter(list2)

          2.4 帶默認(rèn)值的 Dict

          當(dāng)訪問不存在的 Key 時,defaultdict 會將其設(shè)置為某個默認(rèn)值。

          import collections
          collections.defaultdict(type) # 當(dāng)?shù)谝淮卧L問dict[key]時,會無參數(shù)調(diào)用type,給dict[key]提供一個初始值

          2.5 有序 Dict

          import collections
          collections.OrderedDict(items=None) # 迭代時保留原始插入順序

          3. 高性能編程和調(diào)試

          3.1 輸出錯誤和警告信息

          向標(biāo)準(zhǔn)錯誤輸出信息

          import sys
          sys.stderr.write('')

          輸出警告信息

          import warnings
          warnings.warn(message, category=UserWarning)
          # category的取值有DeprecationWarning, SyntaxWarning, RuntimeWarning, ResourceWarning, FutureWarning

          控制警告消息的輸出

          $ python -W all     # 輸出所有警告,等同于設(shè)置warnings.simplefilter('always')
          $ python -W ignore # 忽略所有警告,等同于設(shè)置warnings.simplefilter('ignore')
          $ python -W error # 將所有警告轉(zhuǎn)換為異常,等同于設(shè)置warnings.simplefilter('error')

          3.2 代碼中測試

          有時為了調(diào)試,我們想在代碼中加一些代碼,通常是一些 print 語句,可以寫為:

          # 在代碼中的debug部分
          if __debug__:
          pass

          一旦調(diào)試結(jié)束,通過在命令行執(zhí)行 -O 選項(xiàng),會忽略這部分代碼:

          $ python -0 main.py

          3.3 代碼風(fēng)格檢查

          使用 pylint 可以進(jìn)行不少的代碼風(fēng)格和語法檢查,能在運(yùn)行之前發(fā)現(xiàn)一些錯誤

          pylint main.py

          3.4 代碼耗時

          耗時測試

          $ python -m cProfile main.py

          測試某代碼塊耗時

          # 代碼塊耗時定義
          from contextlib import contextmanager
          from time import perf_counter

          @contextmanager
          def timeblock(label):
          tic = perf_counter()
          try:
          yield
          finally:
          toc = perf_counter()
          print('%s : %s' % (label, toc - tic))

          # 代碼塊耗時測試
          with timeblock('counting'):
          pass

          代碼耗時優(yōu)化的一些原則

          • 專注于優(yōu)化產(chǎn)生性能瓶頸的地方,而不是全部代碼。
          • 避免使用全局變量。局部變量的查找比全局變量更快,將全局變量的代碼定義在函數(shù)中運(yùn)行通常會快 15%-30%。
          • 避免使用.訪問屬性。使用 from module import name 會更快,將頻繁訪問的類的成員變量 self.member 放入到一個局部變量中。
          • 盡量使用內(nèi)置數(shù)據(jù)結(jié)構(gòu)。str, list, set, dict 等使用 C 實(shí)現(xiàn),運(yùn)行起來很快。
          • 避免創(chuàng)建沒有必要的中間變量,和 copy.deepcopy()。
          • 字符串拼接,例如 a + ':' + b + ':' + c 會創(chuàng)造大量無用的中間變量,':',join([a, b, c]) 效率會高不少。另外需要考慮字符串拼接是否必要,例如 print(':'.join([a, b, c])) 效率比 print(a, b, c, sep=':') 低。

          4. Python 其他技巧

          4.1 argmin 和 argmax

          items = [2, 1, 3, 4]
          argmin = min(range(len(items)), key=items.__getitem__)

          argmax同理。

          4.2 轉(zhuǎn)置二維列表

          A = [['a11', 'a12'], ['a21', 'a22'], ['a31', 'a32']]
          A_transpose = list(zip(*A)) # list of tuple
          A_transpose = list(list(col) for col in zip(*A)) # list of list

          4.3 一維列表展開為二維列表

          A = [1, 2, 3, 4, 5, 6]

          # Preferred.
          list(zip(*[iter(A)] * 2))
          瀏覽 43
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩精品免费 | 夜间福利无码视频无码 | 久久久精品电影 | 成年人视频网站 | heyzo超碰 |