Python Coding Interview Questions and Answers


面试题一:逻辑运算赋值

v1 = 1 or 9
v2 = 0 or 9
# print(v1, v2)会输出什么?

我们先举例理解 数字/字符串布尔值 是如何转换的

  • 数字转布尔值
v1 = 0
v2 = bool(v1)
print(v2)       # ---> False
# 总结:只有0转换成布尔值是False,其它都是True。
  • 字符串转布尔值
v1 = ""
v2 = bool(v1)
print(v2)       # ---> False
# 总结:只有空字符串转换成布尔值是False,其他都是True。
  • 也可以把以下数据类型转换为布尔值
bool([]) # 空列表是False,非空列表是True。空集合也是False。
bool(()) # 空元组是False,非空元组是True
bool({}) # 空字典是False,非空字典是True
bool(set()) # 空集合是False,非空集合是True
bool(None) # False
- 布尔值转数字或者字符串使用非常少,了解即可。转换为数字只有0(False)和1(True),转换为字符串只有空字符串("")和字符串("True")。

然后我们再来看这个面试题

```python
v1 = 1 or 9
v2 = 0 or 9
# print(v1, v2)会输出什么?

解: 当和逻辑运算符一起存在时会自动转换为布尔值,根据上面的例子得知,1是True,9也是True,0是False,v1取到第一个值等式就成立了,v2中因为0是False所以还需要继续看后面的值,所以输出1 9 ,v1和v2都为整型。

扩展

v1 = 3>4 or 4<3 and 1==1
print(v1)     # ---> False,有比较运算,先比较是True还是False,再做逻辑运算

v2 = 1 and 9 or "" and 6
print(v2)     # ---> 9
# 在没有()的情况下not优先级高于and,and优先级高于or,即优先级关系为( ) > not > and > or,同一优先级从左往右计算。

参考如下:

Operation

Result

x or y

if x is false, then y, else x

x and y

if x is false, then x, else y

not x

if x is false, then True, else False

由此引出Python运算符优先级,以下表格列出了优先级从高到低的所有运算符。

运算符

描述

**

指数(最高优先级)

~ + -

按位翻转,一元加号和减号(最后两个的方法名为 +@和 -@)

* / % //

乘,除,取模和取整数

+ -

加法、减法

>> <<

右移、左移运算符

&

位'AND'

^ `

`

<= < > >=

比较运算符

<> == !=

等于(判断)运算符,其中<>不等于,类似!=,在python 3中已剔除。

= %= /= //= -= += *= **=

赋值运算符

is is not

身份运算符

in not in

成员运算符

not and or

逻辑运算符,其优先级从高到底依次为 not > and > or


面试题二:字符串反序

value = 'abcdefg'
# 把value的值反序,输出结果为"gfedcba"

这里涉及到的知识点是字符串的公共方法中切片步长, 先举一个字符串切片的例子:

name = "Joney"
print(name[0:3])   # 输出结果是 Jon,这就是字符串切片,获取字符串中一部分字符,更专业的说法是获取子序列。
# 字符串是一个有序的字符集合,索引下标从0开始往右顺序访问。
# 字符串切片其中一个特点是顾首不顾尾,获取方式是 0 =< x < 3,x为切片的结果。
# name[:]输出结果是"Joney",即表示为正无穷和负无穷。
# name[-1]表示最后一个字符y,或者name[-1:]。

再来看一个字符串切片中步长的例子:

name = "JoneyHsiao"
print(name[0:8:2])   # 输出结果是 Jnys, 后面的:2就是步长。
# 意思就是下标值从0开始( 0 =< x < 8),从左往右按顺序每取一个值下标就+2,即下标分别为0,0+2,2+2=4,4+2=6。
# 默认步长是1,这里特别要注意是默认情况下是从左往右按顺序获取。
# 那么能不能从右往左获取呢?答案是可以的。特例:name[-1:0]获取不到子序列,因为是从左往右,无集合。
# 从右往左只需要把步长设置为负值(例如:-1)就可以。
# 例如:name[-1:0:-2],即从右往左(-1 =< x < 0),以步长2获取子序列,输出结果是"oiHeo"。

最后我们来分析面试题:

# 我们已经知道可以用切片的方式输出整个字符串,这是从左往右取负无穷和正无穷
name = "abcdefg"
print(name[:])

# 那么反过来,我们就可以从右往左取负无穷和正无穷
print(name(::-1))   # 输出结果就是反序"gfedcba"

面试题三:Git常用命令

git init
git status
git log
git add .
git commit -m "commit"
git push origin master

面试题四:你是怎么用git做开发的?

  1. 在码云、GitHub或GitLab等代码托管平台创建仓库,创建完之后得到一个仓库地址。
  2. 编写代码中 .....
  3. 将已编写好的代码提交到远程仓库。
  • 初始化
  • 进入一个任意文件夹,文件名最好和远程仓库名称一致
  • git init
  • git config --global user.name "joneyhsiao"
  • git config --global user.email "joneyhsiao@sina.com"
  • git remote add origin https://gitee.com/joneyhsiao/OxusLog.git注意:至此git已经将该文件夹管理起来,以后此文件夹有任何变化,git都会检测到(使用 git status 命令可以查看状态)
  • 代码收集并提交
  • git status
  • git add .
  • git commit -m ''记录"
  • git push origin master # 将本地文件夹下的内容同步到远程仓库。
  • 修改代码或删除文件等对本地文件夹下任何文件做操作。
  • git status
  • git add .
  • git commit -m ''记录"
  • git push origin master # 将本地文件夹下的内容同步到远程仓库。
  • 【避免】如果远程有本地没有的代码,必须先执行:【可能引发合并问题】
  • git pull origin master
  • git status
  • git add .
  • git commit -m ''记录"
  • git push origin master # 将本地文件夹下的内容同步到远程仓库。

面试题五:元组书写规范 -> 必须要有逗号

v1 = 1
v2 = (1)
v3 = (1,)
v4 = ()

print(type(v1), type(v2), type(v3))
# <class 'int'> <class 'int'> <class 'tuple'>
# (1) 是整型,如果最后不加逗号则括号内就是对应的数据类型,v1 等价于 v2
# dialog = "This is %s speaking." % (joney,) 最后加上逗号才是元组,如果不加逗号这里就是字符串
print(type(v4))
# <class 'tuple'>

# 附例:
score = '80 '
int(score)   # 可直接转换为整型
score.isdigit()   # False 因为有空格
score.strip().isdigit()   # True 移除空格

面试题六:集合的关系运算(交集 / 合集 / 差集 / 对称差集 / 包含关系)

  • 交集
a = {1, 2, 3, 4}
b = {3, 4, 5, 6, 7}
print(a.intersection(b)) # {3, 4}
# 或
print(a & b) # {3, 4}
  • 合集,也叫并集(合并去重)
a = {1, 2, 3, 4}
b = {3, 4, 5, 6, 7}
print(a.union(b)) # {1, 2, 3, 4, 5, 6, 7}
# 或
print(a | b) # {1, 2, 3, 4, 5, 6, 7}
  • 差集
a = {1, 2, 3, 4}
b = {3, 4, 5, 6, 7}
# 只存在于 a ,但不存在于 b
print(a.difference(b)) # {1, 2}
# 或
print(a - b) # {1, 2}

# 只存在于 b ,但不存在于a
print(b - a) # {5, 6, 7}
  • 对称差集
a = {1, 2, 3, 4}
b = {3, 4, 5, 6, 7}
# 只存在于 a 或只存在于 b
print(a.symmetric_difference(b)) # {1, 2, 5, 6, 7}
print(a ^ b) # {1, 2, 5, 6, 7}
  • 包含关系
  • in / not in:判断某元素是否在集合内
  • == / !=:判断两个集合是否相等
  • 两个集合之间一般有如下几种关系:
  • 相交 和 不相交
a = {1, 2, 3, 4}
b = {3, 4, 5, 6, 7}
print(a.isdisjoint(b)) # False。判断 a 和 b 两个集合是不是不相交
  • 包含 和 不包含
a = {1, 2, 3, 4}
b = {3, 4, 5, 6, 7}
print(a.issuperset(b)) # False。判断 a 是否包含 b,等同于 a >= b
print(a.issubset(b)) # False。判断 a 是否被 b 包含,等同于 a <= b

面试题七: ==is 有什么区别?

运算符

类型

描述

实例

==

比较运算

等于, 比较(判断)对象是否相等

a == b,如果两对象相等则返回True,否则返回False

is

身份运算

is 是判断两个标识符是不是引用自一个对象

x is y,类似 id(x) == id(y),如果引用的是同一个对象则返回True,否则返回False

is not

身份运算

is not 是判断两个标识符是不是引用自不同对象

x is not y,类似id(a) != id(b),如果引用的不是同一个对象则返回结果True,否则返回False

v1 = [1, 2, 3]
v2 = [1, 2, 3, 4]
v1 == v2 # False
v1 is v2 # False

v1 = [1, 2, 3]
v2 = [1, 2, 3]
v1 == v2 # True
v1 is v2 # False

v1  = [1, 2, 3]
v2 = v1
v1 == v2 # True
v1 is v2 # True

# 出于节省内存的角度思考,Python 对部分简单的字符串和数字(小数据池)(-5 =< x < 257)做了特殊的缓存内存地址优化机制,python解释器因要定义的新变量内容与之前定义过的变量内容相同而不会让新变量占用新的内存空间。
v1 = 'joney'
v2 = 'joney' # 按理 v1 和 v2 应该是不同的内存地址
v1 == v2 # True
v1 is v2 # True,内存地址相同

总结:

  • == 比较值是否相等
  • is 比较内存地址是否相等

TODO 面试题八:什么是深浅拷贝?

TODO 面试题九:Python 2 和 Python 3 的区别

以下这几点区别可以不说,因为是最基础的知识,并不是考察的知识点。

  • 默认解释器编码,python2 -> ASCII,python3 -> UTF-8
  • 输入输出,python2 -> print "" / raw_input(),python3 -> print() / input()
  • 整数的除法。python2只保留整数位,如果要保留小数位,需要导入一个模块。python3正常。
from __future__ import division
value = 3 / 2

python2 -> int / long,python3 -> int

面试题十:列举 Python 的数据类型中都有哪些方法?

  • 整型 int
  • python2 -> int / long,python3 -> int
  • 整数的除法。python2只保留整数位,如果要保留小数位,需要导入一个模块。python3正常。
from __future__ import division
value = 3 / 2
  • 强制转换:
  • int('字符串') 【重要】
  • int(布尔值)
  • 布尔值 bool
  • 强制转换:
bool(0)  # 只有0转换成布尔值是False,其它都是True。
bool("") # 只有空字符串转换成布尔值是False,其他都是True。
bool([]) # 空列表是False,非空列表是True。空集合也是False。
bool(()) # 空元组是False,非空元组是True
bool({}) # 空字典是False,非空字典是True
bool(set()) # 空集合是False,非空集合是True
bool(None) # False
  • 字符串 str
  • 独有方法:upper/lower/split/strip/replace/isdigit/startswith/endswith/format/join/encode
  • 公共方法:
  • len / 索引 / 切片 / 步长 / for循环 / 删除【无】 / 更新【无】
  • 强制转换:
str(999) # "999"
str(True) # "True"
str(["Joney",'Hsiao']) # "['Joney', 'Hsiao']"
",".join(["Joney",'Hsiao']) # 'Joney,Hsiao' 循环每个元素,元素必须是字符串。

# 如果元素是数字,可以使用列表推导,将 int 转换为 str
v1 = ["Joney",'Hsiao', 18]
v2 = [str(i) for i in v1] # ['Joney', 'Hsiao', '18']
",".join(v2) # 'Joney,Hsiao,18'

# 或
nums = [11, 22, 33, 44]
for i in range(0, len(nums)):
    nums[i] = str(nums[i])
result = '_'.join(nums)
print(result)
  • 列表 list
  • 独有方法:append/insert/pop/remove/clear/extend/reverse/sort
  • 公共方法:
  • len / 索引 / 切片 / 步长 / for循环 / 删除 / 更新
  • 强制转换:
  • list("Joney")
v1 = list("Joney")
print(v1) # ['J', 'o', 'n', 'e', 'y']
  • list( (11,22,33,44,) )
v1 = list( (11,22,33,44,) )
print(v1) # [11, 22, 33, 44]
  • 元组 tuple
  • 独有方法【无】
  • 公共方法:
  • len / 索引 / 切片 / 步长 / for循环 / 删除【无】 / 更新【无】
  • 强制转换:
  • tuple('Joney')
v1 = tuple('Joney')
print(v1) # ('J', 'o', 'n', 'e', 'y')
  • tuple([11,22,33,44])
v1 = tuple([11,22,33,44])
print(v1) # (11, 22, 33, 44)
  • 字典 dict
  • 独有方法:keys/values/items/get/pop/update
  • 公共方法:
  • len / 索引 / 切片【无】 / 步长【无】 / for循环 / 修改(存在就修改/不存在就增加) / 删除
  • 集合 set
  • 独有方法:add / discard / update / intersection / union / difference / symmetric_difference
  • 公共方法:len / for循环 / 索引【无】 / 步长【无】 / 切片【无】 / 删除【无】 / 修改【无】

持续更新