写点什么

Python 丨实用技巧 Tips

作者:AXYZdong
  • 2022 年 7 月 14 日
  • 本文字数:3533 字

    阅读完需:约 12 分钟

Python丨实用技巧Tips

Author:AXYZdong

自动化专业 工科男

有一点思考,有一点想法,有一点理性!

定个小小目标,努力成为习惯!在最美的年华遇见更好的自己!

更多精彩文章前往:👉 个人主页


语法糖(Syntactic sugar)

语法糖(Syntactic sugar),也译为糖衣语法,即用更简练的代码表达更复杂的功能。


  • 就像“成语”,文字精炼,含义丰富。

  • 在代码中加糖以后,语法并不改变,但代码会变得更加简洁。


Python 中的语法糖:


  • 切片

  • 上下文管理器

  • 装饰器

  • with 语法糖

  • else 语法糖:for else 、while else 、 try else

  • ...

Python 之禅

在 Python 交互式解释器中输入 import this 就会显示 Tim Peters 的 The Zen of Python


>>> import thisThe Zen of Python, by Tim Peters
Beautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.There should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.Now is better than never.Although never is often better than *right* now.If the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea -- let's do more of those!
复制代码


Python之禅 by Tim Peters
优美胜于丑陋(Python 以编写优美的代码为目标)明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)可读性很重要(优美的代码是可读的)即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)当存在多种可能,不要尝试去猜测而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido )做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)
复制代码

方便的字符串

在 Python 中字符串支持乘法操作,所以可以使用这样的方式输出一些特殊的字符串。


print('*'*20)print(' '*20)print(' '*7+'Python'+' '*7)print(' '*20)print('*'*20)
复制代码


输出结果:


********************                           Python                           ********************
复制代码

灵魂互换

在程序中实现 a 和 b 两个人的灵魂(对应的值)互换。


a = 10b = -10temp = bb = aa = temp
复制代码

×

a = 10b = -10a,b = b,a
复制代码

三目运算符

  • 比较两个数字,输出大的那个:

if a > b:  print(a)else:  print(b)
复制代码


  • 简化

print(a if a>b else b)
复制代码


使用 if-else 简化的写法称为三目运算符(三元表达式) exp1 if contion else exp2

隐式的判断条件

在判断条件中使用隐式的 True 和 False


if 1 == True:  print(True)if 10>15 == True:  print()if a != None:  print()
复制代码


👇

if 1 :  print(True)if 10>15 :  print()if a :  print()
复制代码

简洁的推导式

  • 生成一个列表:

[i**2 for i in range(-5,5) if i%2 ]
复制代码


  • 生成一个集合:

{i**2 for i in range(-5,5) if i%2 }
复制代码


  • 生成一个字典:

{x:y for xy in zip(["a","b"],(1,2))}
复制代码

小整数对象池

Python 为了优化速度,使用了小整数对象池,避免为整数频繁申请和销毁内存空间。

  • 小整数范围 [-5,256]。

  • 这些整数对象会被实现建立好,不会被回收,为变量赋值时直接指向这些建立好的地址。

a = 257b = 257id(a) == id(b)#False
复制代码


a = 0b = 0id(a) == id(b)#True
复制代码


a = 1-1b = 1-1id(a) == id(b)#True
复制代码


简单的字符串在内存使用上同样也有优化,当字符串中不存在空格和特殊字符。


a = "Python"b = "Python"a is b#True
复制代码


a = "Py$thon"b = "Py$thon"a is b#False
复制代码


a = "Py thon"b = "Py thon"a is b#False
复制代码

变量的作用域规则 - LEGB

在 Python 中变量的作用域可以分为四个部分


  • Local(function):函数内的名字空间;

  • Enclosing function locals:外部嵌套函数的名字空间(例如 closure);

  • Global(module):函数定义所在模块(文件)的名字空间;

  • Builtin(Python):Python 内置模块的名字空间。

数据解包

获取一个列表的所有数据

for i in [1, 2, 3]:  print(i)
复制代码


这样方便吗?


解包


  • 使用相同数量的变量接收


a, b, c = [1, 2, 3]print(a, b, c)
复制代码


  • 使用 *


L = [1, 2, 3]print(*L)
复制代码

Python 中的“动态”

  • 在 Python 中声明变量时不需要指定类型。

>>> a = 1>>> b = 'Python'>>> c = [1, 2, 3]>>> print(type(a))<class 'int'>>>> print(type(b))<class 'str'>>>> print(type(c))<class 'list'>
复制代码


  • 在类和对象的使用中可以动态的为对象添加属性和方法。

>>> class student(object):  def __init__(self):    self.age = 18
>>> s = student()>>> s.name = 'axyzdong'>>> print(s.age, s.name)18 axyzdong
复制代码

Python 中的垃圾回收机制

  • Python 的内存管理是由 Python 的解释器负责的,开发人员可以从内存管理事务中解放出来。

  • Python 中的垃圾回收机制以“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题。通过“分代回收”(generation collection)以空间换取时间来进—步提高垃圾回收的效率。


引用计数:当一个对象的引用被创建或者复制时,对象的引用计数加 1;当一个对象的引用被销毁时,对象的引用计数减 1;当对象的引用计数减少为 0 时,就意味着对象已经没有被任何人使用了,可以将其所占用的内存释放了。


标记-清除:不改动真实的引用计数,而是将集合中对象的引用计数复制一份副本,改动该对象引用的副本。对于副本做任何的改动,都不会影响到对象生命周期的维护。


将系统中的所有内存块根据其存活时间划分为不同的集合,每一个集合就成为一个“代”,垃圾收集的频率随着“代”的存活时间的增大而减小。也就是说,活得越长的对象,就越不可能是垃圾,就应该减少对它的垃圾收集频率。那么如何来衡量这个存活时间:通常是利用几次垃圾收集动作来衡量,如果一个对象经过的垃圾收集次数越多,可以得出:该对象存活时间就越长。


分代回收


  1. 默认一个对象被创建出来后,属于 0 代

  2. 如果经历过这一代"垃圾回收"后,依然存活,则划分到下一代

  3. "垃圾回收"的周期顺序为


  • 0 代"垃圾回收"一定次数,会触发 0 代和 1 代回收

  • 1 代"垃圾回收"一定次数,会触发 0 代,1 代和 2 代回收



  • 当 0 代检测 P 了 1 次后,P 若不是垃圾,则 P 转入 1 代。

  • 0 代继续检测,1 代暂不检测。当 0 代检测 10 次,则 1 代开始检测 1 次,P 若不是垃圾,则 P 转入 2 代。

  • 0 代和 1 代继续检测,2 代暂不检测。当 0 代检测 100 次,1 代检测 10 次时,则 2 代开始检测 1 次。


设计的初衷在于:若一个对象能够多次存活,则减少它的检测频率,以此来节约内存。


查看以及修改机制配置参数


垃圾回收器当中,新增对象个数减去消亡对象个数,达到一定阈值的时候,才会触发垃圾检测机制。


可以通过 gc 模块中的 gc.get_threshold()查询参数,也可以用 gc.get_threshold(500, 5, 5)来自定义参数。第一个参数是新增对象个数减去消亡对象个数的值,第二个参数是 0 代被检测几次式触发 1 代的检测,第三个参数是 1 代被检测几次触发 2 代的检测。


>>> import gc>>> print(gc.get_threshold())(700, 10, 10)>>> gc.set_threshold(500,5,5)>>> print(gc.get_threshold())(500, 5, 5)
复制代码


参考文献


  • [1] https://education.huaweicloud.com/courses/course-v1:HuaweiX+CBUCNXX122+Self-paced/courseware/7e910f5dc4234e50babf72606a606339/925d7dcc3a1043529481023c89a7d4b6/


本次的分享就到这里


如果我的文章对你有帮助、如果你喜欢我的文章内容,请 “点赞” “评论” “收藏” 一键三连哦!

听说 👉 点赞 👈 的人运气不会太差,每一天都会元气满满呦!^ _ ^

码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了👉 关注 👈我哦!

如果以上内容有任何错误或者不准确的地方,欢迎在下面👇留个言。或者你有更好的想法,欢迎一起交流学习~~~


发布于: 刚刚阅读数: 4
用户头像

AXYZdong

关注

没有伞的孩子要学会奔跑! 2020.06.01 加入

自动化专业 工科男 有一点思考,有一点想法,有一点理性。 定个小小目标,努力成为习惯。

评论

发布
暂无评论
Python丨实用技巧Tips_Python_AXYZdong_InfoQ写作社区