코드 포함, 20가지 고주파 및 실용적인 Python 사용 팁

1. 혼란스러운 조작

이 섹션에서는 Python의 혼란스러운 작업 중 일부를 비교합니다.

1.1 교체가 있는 무작위 샘플링 및 교체가 없는 무작위 샘플링

import random
random.choices(seq, k=1)  # 长度为k的list,有放回采样
random.sample(seq, k)     # 长度为k的list,无放回采样

1.2 람다 함수의 매개변수

func = lambda y: x + y          # x的值在函数运行时被绑定
func = lambda y, x=x: x + y     # x的值在函数定义时被绑定

1.3 복사와 딥카피

import copy
y = copy.copy(x)      # 只复制最顶层
y = copy.deepcopy(x)  # 复制所有嵌套部分

복사 및 변수 앨리어싱을 결합하면 혼란스러울 수 있습니다.

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]

별칭의 수정은 원래 변수에 영향을 미칩니다.(얕은) 복사의 요소는 원래 목록의 요소의 별칭이며 깊은 복사는 재귀적으로 복사되며 깊은 복사의 수정은 원본에 영향을 미치지 않습니다. 변하기 쉬운.

2. 공통 도구

2.1 CSV 파일 읽기 및 쓰기

import csv
# 无header的读写
with open(name, 'rt', encoding='utf-8', newline='') as f:  # newline=''让Python不将换行统一处理
    for row in csv.reader(f):
        print(row[0], row[1])  # CSV读到的数据都是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})

CSV 파일이 너무 크면 오류가 보고됩니다: _csv.Error: 필드가 필드 제한보다 큽니다(131072). 상한을 수정하여 해결할 수 있습니다.

import sys
csv.field_size_limit(sys.maxsize)

csv는 또한 \t로 구분된 데이터를 읽을 수 있습니다.

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)           # 当predicate为False时停止迭代
# takewhile(lambda x: x < 5, [1, 4, 6, 4, 1]) -> 1, 4

itertools.dropwhile(predicate, iterable)           # 当predicate为False时开始迭代
# dropwhile(lambda x: x < 5, [1, 4, 6, 4, 1]) -> 6, 4, 1

itertools.compress(iterable, selectors)            # 根据selectors每个元素是True或False进行选择
# 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)                                    # 当最短的序列耗尽时停止,结果只能被消耗一次
itertools.zip_longest(*iterables, fillvalue=None)  # 当最长的序列耗尽时停止,结果只能被消耗一次

2.3 카운터

카운터는 iterable에서 각 요소의 발생 횟수를 계산합니다.

import collections
# 创建
collections.Counter(iterable)

# 频次
collections.Counter[key]                 # key出现频次
# 返回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 기본값이 있는 Dict

존재하지 않는 키에 액세스할 때 defaultdict는 키를 기본값으로 설정합니다.

import collections
collections.defaultdict(type)  # 当第一次访问dict[key]时,会无参数调用type,给dict[key]提供一个初始值

2.5 주문형 사전

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

3. 고성능 프로그래밍 및 디버깅

3.1 출력 오류 및 경고 메시지

정보를 표준 오류로 출력

import sys
sys.stderr.write('')

출력 경고 메시지

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

경고 메시지 출력 제어

$ python -W all     # 输出所有警告,等同于设置warnings.simplefilter('always')
$ python -W ignore  # 忽略所有警告,等同于设置warnings.simplefilter('ignore')
$ python -W error   # 将所有警告转换为异常,等同于设置warnings.simplefilter('error')

3.2 코드 테스트

때로는 디버깅을 위해 코드에 일부 코드(보통 일부 인쇄 문)를 추가하려고 합니다. 다음과 같이 작성할 수 있습니다.

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

디버깅이 끝나면 명령줄에서 -O 옵션을 실행하여 코드의 이 부분을 무시합니다.

$ python -0 main.py

3.3 코드 스타일 확인

pylint를 사용하면 많은 코드 스타일 및 구문 검사를 수행할 수 있으며 실행하기 전에 몇 가지 오류를 찾을 수 있습니다.

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

시간 소모적인 코드 최적화의 몇 가지 원칙

  • 전체 코드가 아니라 성능 병목 현상이 발생하는 부분을 최적화하는 데 중점을 둡니다.

  • 전역 변수를 사용하지 마십시오. 지역 변수의 조회는 전역 변수보다 빠르며 전역 변수의 코드 정의는 일반적으로 함수에서 15%-30% 더 빠르게 실행됩니다.

  • .를 사용하여 속성에 액세스하지 마십시오. from module import name을 사용하고, 자주 접근하는 클래스의 멤버 변수 self.member를 로컬 변수에 넣는 것이 더 빠를 것입니다.

  • 가능할 때마다 내장 데이터 구조를 사용하십시오. str, list, set, dict 등은 C로 구현되며 매우 빠르게 실행됩니다.

  • 불필요한 중간 변수 및 copy.deepcopy() 생성을 피하십시오.

  • a + ':' + b + ':' + c와 같은 문자열 스플라이싱은 쓸모없는 중간 변수를 많이 생성하고 ':', join([a, b, c])가 훨씬 더 효율적입니다. 또한 문자열 splicing이 필요한지 여부를 고려해야 하는데, 예를 들어 print(':'.join([a, b, c]))는 print(a, b, c, sep='보다 덜 효율적입니다. ').

Supongo que te gusta

Origin blog.csdn.net/veratata/article/details/128632602
Recomendado
Clasificación