怎样才算熟悉python编程语⾔_怎样才算精通Python?
在这篇⽂章中,我会1)先给出我对精通Python的理解;2)然后给出⼀些Python中有难度的知识点。如果⼤家在看完这篇⽂章之前,已经充分理解了我列出的各个知识点,那么,我相信你已经算是精通Python了。如果不能,我希望这篇回答能让你意识到⾃⼰Python知识还存在哪些不⾜,在之后的学习中,从哪些⽅⾯去改进。
精通是个伪命题
怎样才算精通Python,这是⼀个⾮常有趣的问题。
很少有⼈会说⾃⼰精通Python,因为,这年头敢说精通的⼈都会被⼈摁在地上摩擦。其次,我们真的不应该纠结于编程语⾔,⽽应该专注于领域知识。⽐如,你可以说你精通数据库,精通分布式,精通机器学习,那都算你厉害。但是,你说你精通Python,这⼀点都不酷,在业界的认可度也不⾼。
再者,Python使⽤范围如此⼴泛,⼀个⼈精⼒有限,不可能精通所有的领域。就拿Python官⽹的Python应⽤领域来说,Python有以下⼏个⽅⾯的应⽤:
Web Programming: Django, Pyramid, Bottle, Tornado, Flask, web2py
GUI Development: wxPython, tkInter, PyGtk, PyGObject, PyQt
Scientific and Numeric: SciPy, Pandas, IPython
Software Development: Buildbot, Trac, Roundup
System Administration: Ansible, Salt, OpenStack
如果有⼈真的精通上⾯所有领域,那么,请收下我的膝盖,并且,请收我为徒。
既然精通Python是不可能也是没有意义的事情,那么,为什么各个招聘要求⾥⾯,都要求精通Python呢?我觉得这都是被逼的。为什么这么说呢,且听我慢慢说来。
为什么招聘要求精通Python
绝⼤部分⼈对Python的认识都有偏差,认为Python⽐较简单。相对于C、C++和Java来说,Python是⽐较容易学习⼀些,所以,才会有这么多只是简单地了解了⼀点语法,就声称⾃⼰会Python的⼯程师。
打个⽐⽅,如果⼀个⼯程师,要去⾯试⼀个C++的岗位,他⾄少会⼀本C++的书认真学习,然后再去应聘。Python则不然,很多同学只花了⼀点点时间,了解了⼀下Python的语法,就说⾃⼰熟悉Python。这也导致Python的⾯试官相对于其他⽅向的⾯试官,更加容易遇到不合格的求职者,浪费了⼤家的时间。Python⾯试官为了不给⾃⼰⿇烦,只能提⾼要求,要求求职者精通Python。
怎样才算精通Python
既然精通Python本⾝是⼀件不可能的事情,⽽⾯试官⼜要求精通Python,作为求职者,应该达到怎样的⽔平,才敢去应聘呢?我的观点是,要求精通Python的岗位都是全职的Python开发,Python是他们的主要使⽤语⾔,要想和他们成为同事,你⾄少需要:
1. 能够写出Pythonic的代码(什么是Pythonic的代码,请看我在另⼀个问题下的回答:怎样才能写出pythonic的代码? - 知乎⽤户的回答)
2. 对Python的⼀些⾼级特性⽐较熟悉
3. 对Python的优缺点⽐较了解
这样说可能⽐较抽象,不太好理解。我们来看⼏个例⼦,如果能够充分理解这⾥的每⼀个例⼦,那么,你完全能够顺利通过"精通Python"的岗位⾯试。
敢来挑战吗
1.上下⽂管理器
⼤家在编程的时候,经常会遇到这样的场景:先执⾏⼀些准备操作,然后执⾏⾃⼰的业务逻辑,等业务逻辑完成以后,再执⾏⼀些清理操作。
⽐如,打开⽂件,处理⽂件内容,最后关闭⽂件。⼜如,当多线程程序需要访问临界资源的时候,线程⾸先需要获取互斥锁,当执⾏完成并准备退出临界区的时候,需要释放互斥锁。对于这些情况,Python中提供了上下⽂管理器(Context Manager)的概念,可以通过上下⽂管理器来控制代码块执⾏前的准备动作以及执⾏后的收尾动作。
我们以处理⽂件为例来看⼀下在其他语⾔中,是如何处理这种情况的。 Java风格/C++风格的Python代码:
myfile= open(r'C:\')
try:python怎么读取py文件
for line in myfile:
...use
finally:
myfile.close()
Pythonic的代码:
with open(r'C:\') as myfile:
for line in myfile:
...use
我们这个问题讨论的是精通Python,显然,仅仅是知道上下⽂管理器是不够的,你还需要知道:
1. 上下⽂管理器的其他使⽤场景(如数据库cursor,锁)
上下⽂管理器管理锁
class FetchUrls(threading.Thread):
...
def run(self):
.
..
with self.lock: #使⽤"with"语句管理锁的获取和释放
print 'lock acquired by%s' % self.name
print 'lock released by%s' % self.name
上下⽂管理器管理数据库cursor
import pymysql
def get_conn(**kwargs):
t(('host', 'localhost'),
('port', 3306),
('user'),
('passwd'))
def main():
conn = get_conn(user='laimingxing', passwd='laimingxing')
with conn as cur:
print cur.fetchall()
if __name__ == '__main__':
main()
上下⽂管理器控制运算精度
with decimal.localcontext() as ctx:
ctx.prec = 22
text().prec)
2. 上下⽂管理器可以同时管理多个资源
假设你需要读取⼀个⽂件的内容,经过处理以后,写⼊到另外⼀个⽂件中。你能写出Pythonic的代码,所以你使⽤了上下⽂管理器,满意地写出了下⾯这样的代码:
with open('') as source:
with open('', 'w') as target:
target.ad())
你已经做得很好了,但是,你时刻要记住,你是精通Python的⼈啊!精通Python的⼈应该知道,上⾯这段代码还可以这么写:
with open('') as source, open('', 'w') as target:
target.ad())
3. 在⾃⼰的代码中,实现上下⽂管理协议
你知道上下⽂管理器的语法简洁优美,写出来的代码不但短⼩,⽽且可读性强。所以,作为精通Pytho
n的⼈,你应该能够轻易地实现上下⽂管理协议。在Python中,我们就是要⾃⼰实现下⾯两个协议:
你知道上下⽂管理器的语法简洁优美,写出来的代码不但短⼩,⽽且可读性强。所以,作为精通Python的⼈,你应该能够轻易地实现上下⽂管理协议。在Python中,我们就是要⾃⼰实现下⾯两个协议:
__enter__(self)
__exit__(self, exception_type, exception_value, traceback)当然,更优美的⽅法是使⽤contextmanager装饰器。
2. 装饰器
由于我们这个问题的题⽬是精通Python,所以,我假设⼤家已经知道装饰器是什么,并且能够写简单的装饰器。那么,你是否知道,写装饰器也有⼀些注意事项呢。
我们来看⼀个例⼦:
def is_admin(f):
def wrapper(*args, **kwargs):
("username") != 'admin':
raise Exception("This user is not allowed to get food")
return f(*args, **kwargs)
return wrapper
@is_admin
def barfoo(username='someone'):
"""Do crazy stuff"""
pass
print barfoo.func_doc
print barfoo.__name__
None
wrapper
我们⽤装饰器装饰完函数以后,⽆法正确地获取到原函数的函数名称和帮助信息,为了获取这些信息,我们需要使⽤@functool.wraps。如下所⽰:
import functools
def is_admin(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
("username") != 'admin':
raise Exception("This user is not allowed to get food")
return f(*arg, **kwargs)
return wrapper
再⽐如,我们要获取被装饰的函数的参数,以进⾏判断,如下所⽰:
import functools
def check_is_admin(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
('username') != 'admin':
raise Exception("This user is not allowed to get food")
return f(*args, **kwargs)
return wrapper
@check_is_admin
def get_food(username, food='chocolate'):
return "{0}get food:{1}".format(username, food)
print get_food('admin')
这段代码看起来没有任何问题,但是,执⾏将会出错,因为,username是⼀个位置参数,⽽不是⼀个关键字参数,我们在装饰器⾥⾯,通过('username')是获取不到username这个变量的。为了保证灵活性,我们可以通过inspect来修改装饰器的代码,如下所⽰:
import inspect
def check_is_admin(f):
@functools.wraps(f)
def wrapper(*args, **kwargs):
func_args = allargs(f, *args, **kwargs)
print func_args
if ('username') != 'admin':
raise Exception("This user is not allowed to get food")
return f(*args, **kwargs)
return wrapper
装饰器还有很多知识,⽐如装饰器怎么装饰⼀个类,装饰器的使⽤场景,装饰器有哪些缺点,这些,你们都知道吗?
3. 全局变量
关于Python的全局变量,我们先从⼀个问题开始:Python有没有全局变量?可能你看到这个问题的时候就蒙圈了,没关系,我来解释⼀下。
从Python⾃⼰的⾓度来说,Python是有全局变量的,所以,Python为我们提供了global关键字,我们能够在函数⾥⾯修改全局变量。但是,从C/C++/Java程序员的⾓度来说,Python是没有全局变量的。因为,Python的全局变量并不是程序级别的(即全局唯⼀),⽽是模块级别的。模块就是⼀个Python⽂件,是⼀个独⽴的、顶层的命名空间。模块内定义的变量,都属于该命名空间下,Python并没有真正的全局变量,变量必然属于某⼀个模块。
我们来看⼀个例⼦,就能够充分理解上⾯的概念。三种不同的修改全局变量的⽅法:
import sys
import test
a = 1
def func1():
global a
a += 1
def func2():
test.a += 1
def func3():
module = dules['test']
module.a += 1
func1()
func2()
func3()
这段代码虽然看起来都是在对全局变量操作,其实,还涉及到命名空间和模块的⼯作原理,如果不能很清楚的知道发⽣了什么,可能需要补充⼀下⾃⼰的知识了。
4. 时间复杂度
我们都知道,在Python⾥⾯list是异构元素的集合,并且能够动态增长或收缩,可以通过索引和切⽚访问。那么,⼜有多少⼈知道,list是⼀个数组⽽不是⼀个链表。
关于数组和链表的知识,我想⼤家都知道了,这⾥就不再赘述。如果我们在写代码的过程中,对于⾃⼰最常⽤的数据结构,连它的时间复杂度都不知道,我们⼜怎么能够写出⾼效的代码呢。写不出⾼效的代码,那我们⼜怎么能够声称⾃⼰精通这门编程语⾔呢。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论