python contains类似函数_Python入门简介

Python近几年来热度不断增加,依赖于开发者社区的无私贡献,Python从程序员圈子迅速火到了自动化办公、机器学习、数据分析、运维等领域,作为从脚本早期就关注其发展的使用者,也欣慰自己点亮了一个道路正确的"技能树"。可以说在我遇到Python之之后才开始真正将我的技能带入到了日常生活中,切实的提高了工作效率也改变了我的生活方式。Python就像是一个多年老友,知心而且可靠,遇到的各类问题只要是计算机能做的,我知道它都能帮我高效解决。在这里我想写一个很长的故事,和大家分享Python的各种特点以及我日常工作生活中是如何使用它的。

Python的一些特点

如果你没有装过Python,建议你使用Anaconda一次性搞定各种常用的Python依赖库,Anaconda是一个科学计算、数据处理开发套件,集成了常用的相关Python库并且自带包管理工具,能一站式提供绝大多数常用包。


Anaconda最新版自带的解释器是Python3,Python2和Python3并不兼容,如果你对Python版本没有历史包袱的话,推荐使用Python3,本文所有代码基于Python3演示。


下面正式为大家介绍,可爱的Python。

Python之禅

Python有一个彩蛋,在脚本中import this的话可以打印出”The Zen of Python“,Python之禅,可以认为这是Python的设计思想,也是给各位(不只是Python)程序员的忠告,译文不再完整粘贴,摘录几句——

f5b63944dff2cb8cd1d49af5b7758401.png

大家可以自己尝试翻译一下,也请尽量记住这些忠告,在写代码的时候保持理性和克制。

Jupyter Notebook以及帮助信息

Python的编辑器非常多,PyCharm、Wing、vscode甚至记事本都不影响我们发挥,但是在需要快速验证想法,或者希望快速了解某些库的话个人更推荐Jupyter Notebook,它是一个网页版的IDE,有拼写提示,能快捷的显示各库的帮助信息;网页写代码,服务端执行。对于数据分析、脚本验证再合适不过了。Jupyter Notebook集成在Anaconda中,在终端上输入jupyter notebook,将输出的URL复制到浏览器中即可使用。如果没有已经编写好的脚本,需要新建一个Python3脚本,如图。

fed29d622cb7daaf542443f46a74a468.png

在需要查看某个库/函数的帮助信息时,在要查询的主体后面加'?'即可——

9a57172c75d681f9bbca750ef5720fea.png

想知道库中有哪些类型/函数,使用dir(lib)预览(也可以预览类型的属性和方法)——

cf26b9b71c0992942923c5892144602a.png


希望详细了解语言特性或者库函数的话,还是首选官方网站(https://docs.python.org/3/)
想直接执行dos命令或shell,在语句前加'!'即可——

14ec850188748dd0f910b5a66e0bdc24.png

tab键开始拼写提示。其他还有各种快捷操作和插件,不再详细介绍,感兴趣的同学详细研究吧。

常用数据结构

Python中一切皆对象,甚至包括函数、包、类,都是对象,可以用下面方法验证——

7e58e5a3f7116f619f2a7d66ee10015c.png


因此请了解下面列举的各种类型变量,本质上都是对象。

数值类型

Python的数值类型有int/float/bool/complex几种,需要注意数值类型在Python中是不可变类型,意思是该变量的值不能被改变。


我上面那句没有写错你也没看错,数值类型在Python中的确无法改变,那如下代码发生了什么?

a46a9a5712160ebe07fba6e0486c3b7e.png


a的类型是int,初始值是1。在执行a+=1后,a变量指向的就不再是之前的值1了,而是一个新的对象,也就是说加法执行完毕后a指向的对象变了。具体可以用id来验证,这个函数用来返回变量指向的对象"地址"——

5988875d6ef3ffcc0ae626e4db73994e.png


可以看出执行前后a指向的对象地址已经变了。


这个结论有点颠覆三观,但为了提高执行效率Python的确就是这么实现的。数值类型都是不可变的,其他几种类型同理,不再具体举例了。

字符串

字符串在Python中同样是不可变的——

2ce536447ca1a861912b90cb8fd5453a.png


字符串可以用单引号、双引号和三个单/双引号包括,其中单引号和双引号没有区别,可以在字符串也包含引号时用不同的方式区分,例如

dafc523b06ef3fec9f753e81bc159e7e.png


三个引号包括的内容被完整引用,包括缩进、换行等,例如

9784455f444d7265686548336505d98b.png

除此之外,Python的字符串有大量非常方便的函数,下面举几个简单的例子。

格式化
Python的字符串格式化操作非常简洁,例如想将各种类型变量格式化到一个字符串中,可以

dcd186bf80eb0c3bb1d101e21ab763e8.png


上面代码混合了字符串、数值、字典的格式化,一个format就能搞定。更多的控制细节大家可以自行查询。

字符串重复打印
如何重复打印100次字符串?其他语言可能需要用循环来控制,Python则使用“乘法”来实现——

fe08e6bfc17c679f846a45184f868a1e.png

字符串分割
如果有日志字符串格式类似2020-9-1 19:49:06 [INFO] aaa|bbb|ccc,如果希望抽取时间,可以按空格分割并把的第二个空格前面的字符串合并,例如

46e669cb235e94f1ecf777cf91ded7fb.png


如果想把日志级别抽取出来,除了正则表达式之外,还可以按[ ]分割,例如

316e8d6949df3c11818e05a0fd0fa39a.png


提取bbb一样的道理,例如

ebb0020b8f3bd4d0ba1abea23ea42f60.png

字符串查找in关键字可以用来判断是否包含子串

593677c0cd056b3b1d2a34665208c52c.png

find函数可以用来查找子串出现的位置

8888703eb326bbc301bb723a07ccaea4.png

大小写转换upper/lower函数用来转换字符串的大小写

62a1ffb04f2cfdcaa3539576229a273f.png

去掉空白字符
在文本处理时经常要忽略掉空白字符,例如换行、回车、空格,可以使用strip/lstrip/rstrip清除,例如

8d91a4d3aadc9111537687eac47dbdf6.png

元组

从这里开始就是Python内置的常用容器了,元组(tuple)是一个不可修改的序列,可以随机访问,但无法修改元组本身,也就是说元组创建之后不能增加或删除里面的元素。元组创建方式是t=tuple()t=()——

75bfcbc062751a0137d375fec7aebc2a.png

所谓的元组不能修改,指的是元组本身无法修改,元组中的数据其实是可以改变的——

6fd4317df0daedb755e8f71d5ac84d18.png


元组可以转为其他容器、可以切片也可以迭代、可以随机访问、计算长度等——

325a0fdf4d7a63701c85cc86ca2f5f92.png

346cc804b8e7bf7eec0f2904d7750dff.png

460e216161b1afb77060c2f80f64a324.png

f7dcc7baecdf9a87fcdb9a8fcea1caac.png

c9608d6fe24b1b8d57c060dbf25a6145.png

770512765023cf307ab735ba888f2403.png


值得注意的是如上面第一个例子所示,元组(和其他所有容器)可以保存任意类型对象,类型无需相同。

列表

列表是Python中最常用的容器,它与元组不同之处是可以被修改。创建方式是l=list()l=[]。向列表中追加元素——

59198b877bdc7765b9f71a539614a98a.png

删除列表中元素——

07075bc29c265b74100fa89b03304948.png


合并两个列表——

ef3babcdc879d3876b2a7986e69aac22.png


对列表排序——

e691c5da8e8e441e259c56566901e0c4.png


其他元组支持的操作列表也都支持,不再重复。

集合

集合用来无序保存唯一的元素,创建方式是s=set()s={1},注意{}创建的是字典,因此空集合必须用set()创建。集合可以任意添加和删除元素,常见操作有——

372b1bebc0a4453b894a6b08d2effecd.png


更常用的操作是set之间的操作,例如判断集合的交、并、补——

adf0237c7ae66c10b2d9709ca5cdc160.png

字典

字典(dict)提供了key-value的映射关系,创建字典的方式是d=dict()d={k:v,k2:v2}。可以通过'[]'设置或获取值,例如——

55e21db3382080c7222a14548e3ea30e.png


可以使用del删除映射关系:del d[key]
可以通过key()返回所有的键,values()返回所有值,items()返回所有键值对——

3f96d49bac35acc9a7a6622663bd8c70.png


不存在映射关系时直接访问会抛出异常,如果希望key不存在时能返回默认值,可以使用setdefault()或者get()    

1b1ca8e3512f9abd16d1e60dc99d4058.png

推导式

推导式是Python的一个特色语法糖,能让我们用简洁的代码快速生成容器,上述所有容器均支持推导式,例如——

d0a3d9f7aade2d05b0618357e3e6134d.png


字典一样可以用推导式生成,例如希望将两个列表合并,分别当做字典的key和value——

f5eaf6dec53de6758242168be9138184.png


推导式写起来就和用自然语言描述一样,非常方便。

注意上面的例子中,生成列表和字典时用的是[]{},但生成元组并未直接用(),是因为直接用()的话创建的是生成器对象而非元组。生成器是Python为了节省空间而设计的一种特殊类,它的特点是几乎不占内存但可以和容器一样被遍历,例如——

61b2e1b9a67dfdbed9be8db434082c2f.png

018b4bc969fbb5fd0f034ac2780fa9bf.png

d43ea73430d1317ba459bfd203ee861f.png

上面的例子中Python解释器并未生成0~10000的数字,也没有相应的内存占用,但在遍历操作时每一轮循环生成器对象都会返回下一个数字,因此节省了内存占用(尤其是容器保存较为复杂的对象时),但由于容器并未实际生成,不允许对生成器对象进行随机访问或切片,需要此类操作前可以先转为列表或元组。

for/with

for是Python中循环常用关键字,可以用来遍历容器或生成器对象,例如需要循环10次,可以用如下代码——

a1da9e8a10abe91b1a4659d598e21b47.png

需要遍历容器或生成器对象,可以用如下代码——

95ede8ae1292e5dfeb2484da4dc524b4.png

有时需要遍历容器的前几项,可以用切片——

91208acc100e9491f4105b17f9a6bfad.png

但生成器对象无法切片就不能使用该方法了,粗暴一点可以用一个变量计数——

dddc153d76ab195066c53862e4520829.png

更符合Python风格(pythonic,我下次打算说说这个)做法是用enumerate函数修饰可迭代对象(比如容器或者生成器),该函数返回一个迭代次数、迭代内容构成的元组——

8c130d2de9e01dde913e5f69e37250db.png

with关键字用来实现上下文管理。在C++中一个常用技巧RAII,即在对象的构造和析构中进行资源申请和释放,用语言特性保证资源在合适时机被释放;Python的with关键字即实现类似效果。最常用的场景是打开文件——

897e65395d91d07098670545804b6393.png

with关键字保证了文件在离开with语句块后被关闭,无论do_sth函数是正常返回还是抛出异常。如果想手写出此效果,需要写类似下面的代码——

94423c37c6efcf4c5f90c81edf44276b.png

相比之下非常臃肿。
我们也可以自己编写符合条件的类,实现其他资源的自动管理,只需要实现__enter____exit__方法即可——

7537266355cc5d6b3726c3f355fb6feb.png

C++程序员的疑惑

作为一名传统的C++程序员,Python带来的灵活性和语言特性总是让人是不是的收获意外惊喜(或惊吓),下面列举一些我平时发现的Python有违C++常识的内容。

任意添加属性

解释型语言就可以为所欲为,我可以定义一个空类,在对象中给它增加各种属性——

36ddc7abfd2db4bd47edbb1f75729d6d.png


有人说设计模式是编程语言支持度不足的情况下产生的变通方案,至少在Python这个特性下策略模式不需要复杂设计就能轻松实现——

7cfffce98a471da5504d995d24aeb54a.png

事物总是分两面,有时太灵活的技巧会导致代码维护难度加大,当我们想回归传统程序员,限制对象不能随意增加属性时,可以将支持的属性名放在__solts__中,例如——

47b2d982a68204690323e627aab34297.png

神奇的函数参数

函数默认值
这可以说是Python的一个隐藏的坑了,函数的默认参数只会被计算一次。比如——

68c71cc9d52af6f8162494fb7ed9fcb3.png

上面代码中第二次调用测试函数,竟然返回了[1,1],似乎第二次调用时并没有创建新的list。原因在于函数的默认参数只在函数定义时计算一次,以后多次调用不会再创建新的参数。

函数内改变参数
C++中如果一个函数接收的是对象,在函数内对这个对象的任何修改都是针对函数内临时创建的对象,而非本函数被调用时传入的对象。在Python中,这个原则变的并不十分明显,例如函数接收可变类型的话,函数内修改是可以反映到传入参数的——

d59d743eead0b6bb289979f555062af7.png

9b61a2a0df2658e4e7aea287cd6df2df.png


但是如果传入的是不可变类型(你一定还记得数值类型、字符串类型是不可变类型),那么Python函数的行为和C++类似,函数内的修改无法反映到传入参数——

451fa4f770d057455edbb3faff48c993.png

这也是可以理解的,因为不可变类型是无法修改的,这个原则即使作为参数传给函数时也需要保持。只是我们在编写和阅读代码时,需要保持这样的认识——函数内修改参数的行为与参数的类型是有关系的。

伪多线程

Python的一个遗憾是由于全局锁的存在(GIL,其实GIL并不是Python语言的特性,而是使用范围很广的CPython实现引入的一个机制,这里为了简略描述,就叫Python了请注意辨别)并不支持完整的多线程,在同一个进程内的多个线程是无法并发运行的。好在如果我们的程序是I/O密集型的,依然可以考虑使用多线程来加快运行速度;但如果程序是CPU密集型的话,就需要用多进程来实现真正的并发了。好消息是Python的多进程库提供了和多线程库几乎一致的接口,几乎可以像编写多线程程序一样开发多进程。


限于篇幅具体不再举例子了,感兴趣的同学可以自行查阅官方手册了解接口细节。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值