对于新手来说,Python 中有哪些难以理解的概念


对于新手来说,可能还处于学习的最初阶段,热火朝天的撸袖子写代码,可能还用不上什么装饰器、元类之类的概念,我觉的应该是下面这些:

tab和空格缩进的区别

python的代码块和C++/Java等不同,python不使用花括号来限制代码块的范围,而是使用缩进来限制代码块的范围。

而在缩进的选项上,供程序员选择的有使用tab缩进或者使用空格缩进的两种方式。一些程序员喜欢使用tab缩进,嘲讽那些使用空格的程序员每天写代码要带着**游标卡尺**。使用空格的程序员则自诩用空格更加灵活,不管是用三个空格还是两个空格,都比你tab更加个性化。

最关键的是,这两个东西同时使用的时候,编译器会报错,甜豆腐脑和咸豆腐脑你必须二选一。那么究竟应该使用哪一个更好呢?

我个人推荐使用空格来进行缩进。因为tab在各大平台上的兼容情况不是很好,如果你的代码使用了tab进行缩进,可能就不能做到兼容多平台。各个IDE对空格的显示逻辑是相同的,对tab的显示逻辑则是乱七八糟。有些将tab展开为4个空格,有些将tab展开为8个空格,这简直就是一场灾难。

具体可以参考PEP8 这份文档规定了python的推荐代码风格,新手值得一读。

PEP 8 – Style Guide for Python Codewww.python.org

python空格和tab不能混用 python中tab和空格的区别_python

python2.x 与python3.x的区别

官方在2008年就开始力推python3.x了,但是现在还有很大一部分程序仍然运行的是python2.x,市面上的一些入门教材使用的也是python2.x。虽然不是说这些程序、教材使用python2.x就落伍了,毕竟有一些库仍然只支持python2.x(现在越来越多的库支持python3.x了,而且2020年官方将停止对2.x的维护),但是既然是新手新学,那就应该顺着大潮流,学习3.x。

至于其中的奥妙,各个社区上已经有很多大神解答了,直接搜索就好了。(☄⊙ω⊙)☄

引用变量

来看个代码,我觉得一般新手看了应该会素质三连  : )
class sample:
    def __init__(self, items = []):
        self.items = items

    def append(self, value):
        self.items.append(value)

>>> s1 = sample()       #实例化s1
>>> s2 = sample()       #实例化s2
>>> s1.append('Amos')   #在s1的items列表中加入字符串'Amos'
>>> s1.items            #让我们来看看s1的items列表
['Amos']                #诶哟,想象之中
>>> s2.items            #嘻嘻嘻,给你看个大宝贝
['Amos']                #WTF!!!
事实上,两个sample类的实例中的items列表都是同一个对象,因为这个关键词参数指向的是同一个对象,这个对象在方法定义的时候就已经生成了。

我们可以使用id()函数来检验两个变量是不是指向同一个对象
>>> id(s1.items)
49961416
>>> id(s2.items)
49961416
两个变量指向对象的内存地址都是一样的,结果不言而喻。这个就是引用变量,万物皆对象,这个概念在编程初期,应该算是一个比较难理解的了。

匿名函数以及变量作用域

匿名函数是不是一个比较简单的概念?应该算是吧。

变量作用域是不是一个比较简单的概念?应该也是吧。

来来来,看看这道题。
result = [lambda x: x + i for i in range(10)]
for x in result:
    print(x(10), end=' ')
输出结果是什么,是从10-19的数字吗?

不是的,答案是全都是19! : )lambda在闭包中会保留局部函数

在循环中修改列表

咦,python可以用foreach循环,太爽了,多简洁,多灵活!

看看这个例子:
>>> l = [2, 9, 8, 7, 4, 10, 11, 12, 14]
>>> for x in l:
	if x % 2 == 0:
		l.remove(x)    #老夫在这个列表中不希望看到偶数,成双成对什么的最烦人了

		
>>> l                           #为什么老夫的世界总是不得清净
[9, 7, 10, 11, 14]
这个是因为你在remove的时候,影响了它的索引。4被删除的时候,10向前补位,然后进行下一个索引的循环,就省略了10.(大概就是这个意思吧)

各种魔法方法

__str__和__repr__是什么关系,为什么它们总是成双成对?

__new__ 和 __init__ 好像都可以实例化类

__xxxattr___是不是和属性操作有关系?

为什么我的类不能支持运算符比较? 

新手:嘤嘤嘤???

父类中能使用super()函数吗

这个涉及多重继承的MRO表了。事实上,在父类中是可以使用super()函数的,通过使用super()函数,可以将任务转交给方法解析序列(MRO)上的下一个类。这种操作在python的Mixin类中尤其有用。详情可以看

使用Mixin技术来拓展类定义,实现类功能的可插拔 | Amos H’s blogwww.amoshuang.com