难度指数: ★
重要指数: ★
这是一个送分题,死记硬背即可,答案如下
int float str(字符串) list(列表) tuple(元组) dict(字典) set(集合)
回答到这里,就已经ok了,如果想表现的更完美,还可以把bytes(字节串) 也加上,体现你对基础数据类型的掌握深度,bytes是python3以后才有的数据类型。
难度指数: ★★
重要指数: ★
在函数内使用global关键字
a = 10
def test():
global a
a = 20
test()
print(a) # 20
如果想面试官面前给自己加分,答案就不能止于在函数内部使用global。
如果全局变量是不可变对象,那么使用global就对了,如果全局变量是可变对象,比如是一个字典,那么在函数内使用字典时,无需使用global,直接使用字典即可。
修改全局变量,是一个模糊的表述,是修改变量的指向,还是修改变量所指向对象的内容?我们把问题考虑的全面一点,就区分可变对象与不可变对象来回答。
这个问题,牵扯出了可变对象与不可变对,还有变量的作用于问题,这两部分内容我会在其他面试题里讲解,面试官可能会朝着这两个方向继续提问。
难度指数: ★★★
重要指数: ★★★
python的内置数据类型中,可变对象有列表,字典,集合
不可变对象有int,float, str,元组
以上,请死记硬背
接下来,要回答最关键的部分,他们的区别是什么。
想要回答这个问题,你先要指出python的变量是对象的引用。这是关键的得分点,因为涉及到变与不变这个概念是通过变量重新赋值来阐述的。
不论是可变,还是不可变,都是针对变量所指向的对象的值而言的。
a = 5
a = 6
有人会有疑问,a的值最开始是6,后来重新赋值成6,这分明是可变啊。这里理解的误区在于把变量指向的改变理解对象值的改变。5这个对象就在内存中,它没有发生任何改变,发生改变的是a这个变量的指向从5变成了6
a = [1]
a.append(2)
列表是可变对象,列表里的元素可以增加,可以减少,可以发生变化。
如果你认为已经对可变对象和不可变对象理解了,请看下面这个题目
lst = [1, 2, 3]
for item in lst:
item = item + 1
print(lst)
lst = [[1], [2], [3]]
for item in lst:
item.append(0)
print(lst)
请思考,两次print语句输出的内容分别是什么,答案是
[1, 2, 3]
[[1, 0], [2, 0], [3, 0]]
第一段代码,遍历列表的过程中,虽然执行了对item加1的操作,但是,item仅仅是指向了列表里的元素,而列表里的元素都是不可变对象,你无法修改它。item = item + 1 这条语句,创建了一个新的对象,然后重新赋值给item,item改变了指向,没有改变列表列的任何数据。
第二段代码,遍历列表的过程中,item指向了列表lst中的元素,而lst中的元素都是列表,item.append(0)执行时,并没有改变item的指向,而是向所指向的列表里添加新的元素。
关于可变对象和不可变对象的理解,你可以参考这两篇文章
难度指数: ★★★
重要指数: ★★★
理解变量作用域,是理解闭包,装饰器的关键。
对于这个问题,我们首先要回答出python的变量有几种作用域
对于这些概念,我们用最简单的方法来理解
局部作用域是指函数内的作用域,函数内的变量自然也就是局部变量
嵌套作用域,一个函数的内部又定义了一个函数,那么这样就产生了嵌套作用域,嵌套作用域是一个相对概念
全局作用域,每个模块都是一个全局作用域
内置作用域,系统内固定模块里定义的变量,如预定义在builtin 模块内的变量
如果编码习惯不好,内置作用域会产生一些奇怪的问题
a = 3
b = 5
sum = a + b
print(sum)
lst = [1, 2, 3]
print(sum(lst))
上面的代码会报错
TypeError: 'int' object is not callable
这个错误产生的原因是因为第3行的变量sum 覆盖了内置作用域的sum函数,最后一行代码中,sum是一个int类型的数据,而不是内置函数sum。
难度指数: ★★★
重要指数: ★★
is是身份运算符,而 == 是比较关系运算符
对于变量a, b ,如果他们内存地址相同,则a is b 的结果是True
如果a, b 的值相同,a == b 的结果是True
那么,有没有什么例子,是a == b成立,而a is b不成立的呢?
a = [1]
b = [1]
print(a == b) # True
print(a is b) # False
print(id(a), id(b))
使用id()可以查看对象的内存地址,a和b的内存地址是不相同的。
在交互式解释器里执行下面的代码
>>> a = 98434
>>> b = 98434
>>> a is b
False
>>> a == b
True
>>> id(a), id(b)
(2138843672464, 2138875607760)
这个例子可以更加有力的解释is 和 == 的区别,这段代码一定要在解释器里执行,如果在pycharm里执行,得到的结果会不一样,因为它运行代码的机制与解释器不同。
这个题目如果继续深挖,就挖到了python的内存池技术,还是在解释器里执行代码
>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = -5
>>> b = -5
>>> a is b
True
为啥a is b的结果是True呢?python认为-5到256的整数是经常被使用的,因此在解释器启动时就创建了这些对象并且放在内存池中,你每次使用这些小的整数时,用的都是内存池里的对象,这样就避免了反复申请创建新对象。
难度指数: ★
重要指数: ★★
一定要用join
lst = ['I', 'like', 'python']
string = ' '.join(lst)
print(string)
string = ''
for item in lst:
string += item + " "
print(string)
相比于使用+ 对字符串进行连接,join编写代码更容易,当有大量字符串需要连接时,join的速度更快,关键的原因在于使用+连接字符串时,每一次操作都新建一个字符串对象来保存连接后的结果,而join则可以事先申请好一片内存来存储连接后的字符串,避免反复创建字符串对象。
QQ交流群: 211426309