1. 不要在 for 循环后面写 else 块

In [40]: for i in range(3):....:     print i....: else:....:     print "end"....:
0
1
2
end

记住一点:for 循环里面有 break 时 else 不会执行,否则执行完 for 循环会继续执行 else 语句

2. 函数传递

Python函数参数传递注意点:

  • 对于可变的对象的修改在函数外部和内部都可见,调用者和被调用者共享这个对象。
  • 而对于不可变对象,由于并不能真正被修改,因为修改一般都是通过生成一个新的对象然后赋值来实现的。

3. 如何避开变量作用域的陷阱

全局变量简单说就是这3点:

  • 全局变量是位于模块文件内部的顶层的变量名。
  • 全局变量如果是在函数内被改变的话,一定要用global。
  • 全局变量名在函数内部不经过声明也可以被引用。

4. 函数内的变量解析原则

有的书上叫 LEGB 法则,其实讲白了就是下面 4 个过程,当在函数中使用没有声明过的变量时,Python 的搜索顺序是:

  • 先是在函数内部的本地作用域(L)
  • 然后是在上一层的函数的本地作用域(E)
  • 然后是全局作用域(G)
  • 最后是内置作用域(B)

5. 全局解释器锁(GIL)

是什么原因导致多线程不快反慢的呢?

原因就在于 GIL ,在 Cpython 解释器(Python语言的主流解释器)中,有一把全局解释锁(Global Interpreter Lock),在解释器解释执行 Python 代码时,先要得到这把锁,意味着,任何时候只可能有一个线程在执行代码,其它线程要想获得 CPU 执行代码指令,就必须先获得这把锁,如果锁被其它线程占用了,那么该线程就只能等待,直到占有该锁的线程释放锁才有执行代码指令的可能。

因此,这也就是为什么两个线程一起执行反而更加慢的原因,因为同一时刻,只有一个线程在运行,其它线程只能等待,即使是多核CPU,也没办法让多个线程「并行」地同时执行代码,只能是交替执行,因为多线程涉及到上线文切换、锁机制处理(获取锁,释放锁等),所以,多线程执行不快反慢。

但是多线程有个问题,怎么解决共享数据的同步、一致性问题,因为,对于多个线程访问共享数据时,可能有两个线程同时修改一个数据情况,如果没有合适的机制保证数据的一致性,那么程序最终导致异常,所以,Python之父就搞了个全局的线程锁,不管你数据有没有同步问题,反正一刀切,上个全局锁,保证数据安全。这也就是多线程鸡肋的原因,因为它没有细粒度的控制数据的安全,而是用一种简单粗暴的方式来解决。

6. is 和 == 的区别

官方文档中说 is 表示的是对象标示符(object identity),而 == 表示的是相等(equality)。is 的作用是用来检查对象的标示符是否一致,也就是比较两个对象在内存中的地址是否一样,而 == 是用来检查两个对象是否相等。

我们在检查 a is b 的时候,其实相当于检查 id(a) == id(b)。而检查 a == b 的时候,实际是调用了对象 a 的 --eq()–方法,a == b 相当于 a.–eq–(b)。

总结一下,is 是检查两个对象是否指向同一块内存空间,而 == 是检查他们的值是否相等。可以看出,is 是比 == 更严格的检查,is 返回True表明这两个对象指向同一块内存,值也一定相同。

Python里和None比较时,为什么是 is None 而不是 == None 呢?
这是因为None在Python里是个单例对象,一个变量如果是None,它一定和None指向同一个内存地址。而 == None背后调用的是–eq–,而 eq 可以被重载,

7. 连接字符串用 join 还是 +

字符串是不可变对象,当用操作符+连接字符串的时候,每执行一次+都会申请一块新的内存,然后复制上一个+操作的结果和本次操作的右操作符到这块内存空间,因此用+连接字符串的时候会涉及好几次内存申请和复制。而join在连接字符串的时候,会先计算需要多大的内存存放结果,然后一次性申请所需内存并将字符串复制过去,这是为什么join的性能优于+的原因。所以在连接字符串数组的时候,我们应考虑优先使用join。

8. 函数可以在容器中使用

函数可以容器中使用,比如列表,字典里面象参数一样使用:

def show_apple(price):print "The apple's price is {0}".format(price)def show_orange(price):print "The orange's price is {}".format(price)func_dict = {'apple': show_apple, 'orange': show_orange}def main(fruit, price):func_dict.get(fruit)(price)main('apple', 10)
main('orange', 8)

9. __new__和__init__的区别

#实际上,__init__函数并不是真正意义上的构造函数,__init__方法做的事情是在对象创建好
#之后初始化变量。真正创建实例的是__new__方法。
class Person(object):def __init__(self, name, age):print("in __init__")self._name = nameself._age = agedef __new__(cls, *args, **kwargs):print("in __new__")instance = object.__new__(cls, *args, **kwargs)return instancep = Person("li", 20)## 代码输出
in __new__
in __init__
'''上面的代码中实例化了一个Person对象,可以看到__new__和__init__都被调用了。
__new__方法用于创建对象并返回对象,当返回对象时会自动调用__init__方法进行初始化。
__new__方法是静态方法,而__init__是实例方法。'''
  • __new__至少要有一个参数 cls,代表当前类,此参数在实例化时由 Python 解释器自动识别。

  • __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以 return 父类(通过 super(当前类名, cls))__new__出来的实例,或者直接是 object 的__new__出来的实例。

  • __init__有一个参数 self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值。

  • 如果__new__创建的是当前类的实例,会自动调用__init__函数,通过 return 语句里面调用的__new__函数的第一个参数是 cls 来保证是当前类实例,如果是其他类的类名;那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。

10. with 与上下文管理器

with open('test.txt', 'w') as f:f.write('Hello world')'''上面的with代码背后发生了些什么?我们来看下它的执行流程首先执行open('output', 'w'),返回一个文件对象
调用这个文件对象的__enter__方法,并将__enter__方法的返回值赋值给变量f
执行with语句体,即with语句包裹起来的代码块
不管执行过程中是否发生了异常,执行文件对象的__exit__方法,在__exit__方法中关闭文件。
这里的关键在于open返回的文件对象实现了__enter__和__exit__方法。
一个实现了__enter__和__exit__方法的对象就称之为上下文管理器。__enter__方法在语句体执行之前进入运行时上下文,__exit__在语句体执行完后从运行时上下文退出。
在实际应用中,__enter__一般用于资源分配,如打开文件、连接数据库、获取线程锁;
__exit__一般用于资源释放,如关闭文件、关闭数据库连接、释放线程锁。我们先来看下__enter__和__exit__方法的定义:__enter__() - 进入上下文管理器的运行时上下文,在语句体执行前调用。
如果有as子句,with语句将该方法的返回值赋值给 as 子句中的 target。__exit__(exception_type, exception_value, traceback) - 退出与上下文管理器相关的
运行时上下文,
返回一个布尔值表示是否对发生的异常进行处理。如果with语句体中没有异常发生,
则__exit__的3个参数都为None,即调用 __exit__(None, None, None),
并且__exit__的返回值直接被忽略。如果有发生异常,则使用 sys.exc_info
得到的异常信息为参数调用__exit__(exception_type, exception_value, traceback)。
出现异常时,如果__exit__(exception_type, exception_value, traceback)返回 False,
则会重新抛出异常,让with之外的语句逻辑来处理异常;如果返回 True,则忽略异常,
不再对异常进行处理。'''

我们来自己定义一个简单的上下文管理器。这里不做实际的资源分配和释放,而用打印语句来表明当前的操作。

class ContextManager(object):def __enter__(self):print("[in __enter__] acquiring resources")def __exit__(self, exception_type, exception_value, traceback):print("[in __exit__] releasing resources")if exception_type is None:print("[in __exit__] Exited without exception")else:print("[in __exit__] Exited with exception: %s" % exception_value)return Falsewith ContextManager():print("[in with-body] Testing")

运行上面代码输出以下内容:

[in __enter__] acquiring resources
[in with-body] Testing
[in __exit__] releasing resources
[in __exit__] Exited without exception

11. 浅拷贝与深拷贝

Python中对象的赋值实际上是简单的对象引用,也就是说,当你创建一个对象,然后把它复制给另一个变量的时候,Python并没有拷贝这个对象,而是拷贝了这个对象的引用。

In [1]: a = [1,2,3,4]In [2]: b = aIn [3]: id(a)
Out[3]: 140555756386496In [4]: id(b)
Out[4]: 140555756386496In [5]: id(a) == id(b)
Out[5]: True

浅拷贝

一般使用copy.copy(),可以进行对象的浅拷贝。它复制了对象但对于对象中的子对象,依然使用原始的引用。

In [7]: import copyIn [8]: a = [1, [1,2,3,4]]In [9]: b = copy.copy(a)In [10]: id(a)
Out[10]: 140555756497592In [11]: id(b)
Out[11]: 140555772667448In [12]: id(a) == id(b)
Out[12]: FalseIn [13]: id(a[1])
Out[13]: 140555756497376In [14]: id(a[1]) == id(b[1])
Out[14]: True# a[1] 和 b[1] 指向同一个对象

深拷贝

深度拷贝需要用copy.deepcopy()进行深拷贝。它会复制一个容器对象,以及它里面的所有元素(包含元素的子元素)

In [15]: a = [2, [3,4,5,6]]In [16]: b = copy.deepcopy(a)In [17]: id(a) == id(b)
Out[17]: FalseIn [18]: id(a[1]) == id(b[1])
Out[18]: False# a[1] 和 b[1] 指向不同的对象

12. 字典排序

In [23]: dd = {'cc':1, 'bb':2, 'aa':3}In [24]: dd
Out[24]: {'aa': 3, 'bb': 2, 'cc': 1}In [25]: sorted(dd.iteritems(), key=lambda x:x[0]) #表示按照key排序
Out[25]: [('aa', 3), ('bb', 2), ('cc', 1)]In [26]: sorted(dd.iteritems(), key=lambda x:x[1]) #表示按照value排序
Out[26]: [('cc', 1), ('bb', 2), ('aa', 3)]

13. 字典取值

建议:尽量用dict.get()来代替dict[key]

14. 字典中提取部分子集

In [27]: students_score={'jack':80,'james':91,'leo':100,'sam':60}In [28]: good_score={name:score for name,score in students_score.items() if score>90}In [29]: good_score
Out[29]: {'james': 91, 'leo': 100}

15. 字典的翻转

In [30]: a = {'a':1, 'b':2, 'c':3}In [31]: invert_a = dict([(v, k) for k, v in a.iteritems()])In [32]: invert_a
Out[32]: {1: 'a', 2: 'b', 3: 'c'}

16. 可变与不可变类型

将一个整数变量传递给函数,函数对它进行操作,但原整数变量a不发生变化。对于基本数据类型的变量,变量传递给函数后,函数会在内存中复制一个新的变量,从而不影响原来的变量。(我们称此为值传递)。

In [4]: a = 1In [5]: def change_integer(a):...:     a = a + 1...:     return a...: In [6]: change_integer(a)
Out[6]: 2In [7]: a
Out[7]: 1

对于表来说,表传递给函数的是一个指针,指针指向序列在内存中的位置,在函数中对表的操作将在原有内存中进行,从而影响原有变量。 (我们称此为指针传递)

In [1]: b = [1,2,3]...: def change_list(b):...:     b[0] = b[0] + 1...:   return b...: In [2]: print change_list(b)
[2, 2, 3]In [3]: b
Out[3]: [2, 2, 3]

注意:元组是不可变的,但是元组里面子元素如果含有列表,则列表子元素又是可变的

>>> t = (1,2,[3,4], 5)
>>> id(t)
48192144
>>> t[2].append(10)
>>> t
(1, 2, [3, 4, 10], 5)
>>> id(t)
48192144

Python 典型错误及关键知识点相关推荐

  1. 正确姿势避坑 Python 中的6个典型错误

    点击关注我哦 一篇文章带你使用正确姿势避坑 Python 中的6个典型错误 Python是一种高级的动态脚本语言.它易于使用的特性使得它非常流行,并且在最近几年得到了扩展.易用性也从易滥用开始.我们列 ...

  2. python 进阶知识点_高效率 Python 进阶:10 个关键知识点与特性

    作为一个语法非常简洁.自由的动态语言,Python 在编程语言行列中这些年的发展无疑是个成功的典范.它因在 Web 开发.数据科学.AI 算法等方向的广泛使用而为人熟知. 再宏大的"软件大厦 ...

  3. 选择python培训机构的关键考核五大因素,让你永不吃亏!

    近几年,对于Python技术在人工智能领域的广泛使用,想要学习Python技术的人越来越多,市面上的Python培训机构也多了起来,如何选择适合的Python培训机构成了困扰大家的问题,下面小编就我大 ...

  4. python语法错误概述_python语法错误

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 我是python中的新手,当我想在模块中编译代码时,我遇到语法错误:invail ...

  5. python返回错误提示_python 错误处理

    在程序运行的过程中,如果发生了错误,可以事先约定返回一个错误代码,这样,就可以知道是否有错,以及出错的原因.在操作系统提供的调用中,返回错误码非常常见.比如打开文件的函数open(),成功时返回文件描 ...

  6. python运行错误-Python在运行中发生错误怎么正确处理方法,案例详解!

    在程序运行的过程中,如果发生了错误,可以事先约定返回一个错误代码,这样,就可以知道是否有错,以及出错的原因.在操作系统提供的调用中,返回错误码非常常见.比如打开文件的函数open(),成功时返回文件描 ...

  7. VINS-Mono关键知识点总结——前端详解

    VINS-Mono关键知识点总结--前端详解 VINS-Mono关键知识点总结--前端详解 1. VINS-Mono的前端流程概述 2. setMask() 函数的作用 3. rejectWithF( ...

  8. 视觉SLAM总结——SVO中关键知识点总结

    视觉SLAM总结--SVO中关键知识点总结 视觉SLAM总结--SVO中关键知识点总结 1. 为什么叫半直接法视觉里程计? 2. SVO的优缺点是什么? 3. SVO的整体框架是怎样的? 4. 分别介 ...

  9. kylin调优,项目中错误总结,知识点总结,kylin jdbc driver + 数据库连接池druid + Mybatis项目中的整合,shell脚本执行kylin restapi 案例

    关于本篇文章的说明: 本篇文章为笔者辛苦劳作用了一整天总结出来的文档,大家阅读转发的时候请不要吝啬写上笔者:涂作权 和 原文地址. 由于笔者所在环境没有人用过kylin,笔者也是自学官网,阅读书籍 将 ...

最新文章

  1. 慕课网 深入浅出javascript 笔记
  2. [BZOJ 5093]图的价值
  3. 虚拟form 下载文件
  4. IJCAI 2021 ICAPS 2021自动强化学习挑战赛正式开赛
  5. 1.关于QT中json数据处理和密码md5加密
  6. 【百度地图API】如何制作可拖拽的沿道路测距
  7. 从二进制数据流中构造GDAL可以读取的图像数据(C#)
  8. 深度学习笔记_基本概念_Depthwise卷积与Pointwise卷积
  9. show processlis
  10. 推荐几款php探针,PHP探针推荐:检测服务器环境好帮手
  11. 腾讯云超级播放器实现无直播占位图,有直播播放视频
  12. 直播电商源码,实现直播音视频的推流
  13. vrep系列教程(一)——熟悉vrep
  14. JS实现新年倒计时动画特效+音乐案例
  15. 【寒江雪】Go实现组合模式
  16. ios 获取芝麻信用分
  17. Linux:邮箱客户端
  18. Halcon contour相关操作
  19. 花旗银行java面试_花旗金融—面经(已offer)
  20. 国内最优质的10个小众网站,你知道几个?

热门文章

  1. 一文吃透JAVA定时器格式
  2. 2022-2028年中国激光脱毛仪行业市场调查研究报告
  3. Ubuntu 安装 ffmpeg
  4. FastAI 课程学习笔记 lesson 1:宠物图片分类
  5. Google Colab 免费GPU服务器使用教程 挂载云端硬盘
  6. 本机无法访问虚拟机上的nignx
  7. LeetCode简单题之数组中两元素的最大乘积
  8. TensorRT 数据格式说明
  9. 如何使用TensorCores优化卷积
  10. Json文件解析(上)