Python高级编程技巧

一、坑坑坑

1.1 并行编程坑

  • mutiproccesssing多进程不能共享主进程的全局变量、甚至常量。如果需要共享常量可以直接传参。如果是要使用共享变量,只能使用mutiproccesssing.Manager()下面的共享变量工具了。
  • PARL: 可以通过注解的方式,将Python的多线程方便的转换成真实并行。
    在这里插入图片描述

1.2 全局变量坑

  • python全局变量不能在函数内被修改,除非再用global关键字声明。

1.3 中文编码坑

  • 考虑旧版本兼容性,代码中含中文的话,文件头声明# coding:utf-8

1.4 Python类成员变量初始化坑

  • 危险操作: 在init()方法外直接定义列表或字典这类可变对象,如下NODE类中的children,这样实例化的所有对象的children都会指向同一地址(类似全局变量),导致修改一个对象的children列表,其他NODE对象的children列表都会一起改变,可通过id()函数检测变量地址。但使用该方法定义int或字符串这类不可变对象时时安全的。

    ## 危险1:init方法外定义可变类型变量
    class NODE:
    	children = []
        def __init__(self):
            pass
    
    ## 危险2:init方法内定义但设置了函数默认参数
    class NODE:
        def __init__(self, children=[1,2]):
    		self.children = children
    
  • 安全的初始化操作如下,建议所有变量初始化在__init()__方法下进行,且可变类型的变量不可以设置默认函数参数,否则也会导致共享变量。

    # 安全定义
    class NODE:
        def __init__(self):
            self.children = []
    

二、大道至简Pythonic

自己总结的一些代码规范, 欢迎补充和意见:

  • 参数分离 如果有较多的常量参数设置,独立一个settings.py文件出来,如setting.version, 如果参数较少,在当前文件前面声明即可。
  • 链式比较 points[3][0] == points[0][0] < points[1][0] == points[2][0], 有一个条件不成立则返回False
  • 条件赋值 a = b if expr else c
  • 默认对象
    # 解释器会自动给赋值为省略号的变量生成一个默认值(默认对象、默认函数)。
    def PLUS(a=..., b=...): ...
    
    
  • 函数式编程 熟练运用常用的函数式编程,代码可读性和coding效率可以直接蹭蹭上涨一个段位啊,spark分布式开发中有很多共同之处,包括但不限于:
    filter() # 按条件过滤, 当你想从列表/字符串中按条件移除元素时是否感觉很难受?
    sorted() # 排序,任何自定义的元素类型
    map()	 # 1 to 1 映射
    reduce() # 迭代
    
  • generator 节省内存提效率利器
  • 封装!封装! 封装是很重要的编程技巧,很多语言都适用,中小型项目中(我也没写过啥大项目),要注意类的封装、模块的封装、函数的封装。积极运用下划线_区分私有共有资源。
  • 注释 合理的封装加上注释,完美!
  • 日志、进度条 对提高程序使用体验来说很重要的好伐
  • 下划线 使用下划线来接收不想做处理的返回值。例如_, data = getData()
  • f-string 别再傻傻的用以前的格式化字符串了,python3.6之后,你可以这么玩:
    name 	 = geekhch
    now_time = time.strftime("%m %d", time.localtime())
    msg      = f'hello, {name}, today is {now_time}'  # 要注意单引号双引号匹配
    
  • 不要灵魂的记忆化搜索 Python实现了记忆化搜索的装饰器,对函数传入值进行hash后作为key,将对应的返回值缓存到map中,从而避免重复计算。
    from functools import cache
    @cache
    def dfs(args):
    	pass
    
  • 列表元素的布尔操作 对列表中所有元素取逻辑与:all([a,b,c,d]), 对所有元素取逻辑或:any([a,b,c,d])

三、代码规范

任何代码风格中,命名规范都是最重要的point之一吧, 一般来说,只要自己的代码风格统一即可,但每种语言都有约定俗成的规范。 !! 如果命名不能准确表达含义,一定要加注释,多花几秒的时间,潜力无限 !!

  • 类命名- 大驼峰
  • 普通函数命名- 全小写、字母开头、下划线分割
  • 私有函数命名- 以单个下划线开头
  • 变量命名- 普通变量与函数规则相同 status_now,
  • 全局变量常量- 全大写,下划线分割单词,如NETWORK_STATUS
  • 等号对齐- 多个等式上下排列, 尽量对齐等号

四、高级操作

知识点先码着,有空再补教程

  • 函数式编程
  • 装饰器
# 使用装饰器实现main函数执行时间统计功能
def print_execute_time(func):
    '''函数执行时间装饰器'''
    from time import time
    def wrapper(*args, **kwargs):
        start = time()
        func_return = func(*args, **kwargs)
        end = time()
        print(f'{func.__name__}() execute time: {end - start}s')
        return func_return
    return wrapper

@print_execute_time
def main():
	time.sleep(1.2)
  • 并行编程mutiproccessing
  • 注解@符号, 通常与装饰器结合使用

五、一些感动到哭的python工具包

  • loguru 日志工具,一行导入,免配置使用,彩色日志。from loguru import loglogger.add(filepath)
  • tqdm 进度条工具 from tqdm import tqdm
  • docopt 命令行参数解析工具,只需要按照要求写好usages以及options, 就能自动检查程序命令行参数。功能与argparse相似。
    from docopt import docopt
    args = docopt(__doc__)
    
  • sqlite3 一个简易数据库,适合一些稍大的数据集的快速磁盘索引。比如需要加载一个5GB的数据集中的某一条,直接使用文本读取的话需要检索整个文件,使用sqllite会快很多。
  • random.choices 按照概率权重选择元素(轮盘赌的实现)

六、Python数据结构原理

6.1 列表list

  • list底层是连续内存分配,类似C++的vector。因此要避免频繁的插入操作,即使是在列表头插入也一样很慢。
  • 列表翻转arr = arr[::-1]或者arr.reverse()复杂度为O(n), 其中前者性能低于后者,因为前者需要拷贝到新的内存。reversed(list_obj)返回一个反向的迭代器。

七、Python面向对象

  • python继承时,变量名不能多态。(根据初始化的顺序,一个对象只能有一个变量名,无法通过super()取变量值)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值