编程语言的面试,除了核心知识点和语法的考察外,还会有一些考察面试者语言熟练程度的小问题,这些问题虽然涉及的都是一些基本知识点,但是需要使用者能做到活学活用,见多识广,化繁为简。解决同样一个问题,别人写了十几行代码,你却能两三行轻描淡写的搞定,那你的机会就会大大增加,下面就来看一下python里的小trick
1.变量交换
想到变量交换,很多人第一想法就是创建一个中间变量temp来中转一下,这样写没有问题,但是太繁琐,python里一行代码就可以完成这个操作
x,y = 10, 20
x,y = y,x
print(x,y)
>>20 10
2.序列的反转
这里使用切片的方式,将第三个参数设为-1,表示反向
a= [1,2,3,4,5]
b= 'hello'
print(a[::-1])
>>[5, 4, 3, 2, 1]
print(b[::-1])
>>'olleh'
list的反转有专门的函数reverse(), a.reverse()会直接修改a的顺序,没有返回值
3.链式比较
我们有个变量a,要判断它是否大于1小于2,一般会想到使用and 关键字连接两次判断,其实python里可以直接写成数学公式一样的比较,
a=1.5
if 1<a<2:
print('yes')
>>yes
b= 2<a<3
>>false
4.查找list 中出现次数最多的元素
这个问题解决方法有很多,最简单的就是遍历list,一个个的计算出现次数和上一个比,如果次数大于上一个就替换上一个,否则继续使用上一个元素做比较,这种方法没什么好说的。还有一种方法就是使用collections 模块的Counter方法,这个方法可以一次性返回每个元素出现的次数,返回包含tuple的list(这个方法还可以用来检查两个单词是不是字母相同的)
from collections import Counter
a=[1,2,2,3,3,3]
c=Counter(a)
print(c)
>>Counter({3: 3, 2: 2, 1: 1})
a.most_common(1)[0][0]
>>3
还有一种更简单的方法,是用max函数,一般我们使用max函数只关注第一个参数,其实第二个参数有时有画龙点睛的作用
max函数的定义为:
max(iterable, key, default)
第二个参数是用来处理iterable里每一个的值的,一般为lambda函数,处理完每一个元素后再来比较max,
a=[1,2,2,3,3,3]
m =max(set(a), key=a.count)
>>3
试想面试中,你这行代码一写,绝对在一众平庸的答案中脱颖而出~~
5.zip函数
这个函数可能平时不怎么用到,但是当你需要它的时候,一定要记得它,因为它能为你节省几十行代码
这个函数的作用是让多个可迭代的对象相同位置的元素打包成元组,最后返回这些元组组成的列表。如果多个可迭代对象的长度不一样,则只取最短的那个长度
a=[1,2,3]
b=[4,5,6]
c=[7,8,9,10]
ab=zip(a,b)
>>[(1,4),(2,5),(3,6)]
ac=zip(a,c)
#注意,python2里直接返回列表,python3返回的是个对象,需使用list函数查看结果,
#并且为了节约内存,zip对象只能访问一次!
>>[(1,7),(2,8),(3,9)]
zip(*ab)
>>[(1,2,3),(4,5,6)]
另外,python里我们可以使用星号(*)来传递列表参数到函数中去,星号会自动把列表解压成单个参数:
def foo(a,b):
print(a,b)
L=(1,'a')
foo(*L)
>>1 'a'
利用这个属性我们可以把zip 压缩过的结果,再解压回来
a=[1,2,3], b=['a','b','c']
zp=zip(a,b)
zip(*zp)
>>[(1, 2, 3), ('a', 'b', 'c')]
6.查看对象大小
python标准库里有很多非常实用的工具,比如这里我们就可以使用sys模块的getsizeof()方法
获得对象占用空间
7. for else
else 这个语句不止可以和if 搭配,和for 也能成双成对,
当for 语句迭代完后就会进入else语句,所以一般情况下这个else语句总是会执行的,如果想跳过,就需要在
for语句后面使用break强制跳出for 循环。
for i in range(10):
if i == 5:
print('get it')
break#注意,这里必须调用break跳出,不然迭代完成后就会进入else里!
else:
print('no found!')
>> get it
8. @staticmethod 和 @classmethod
类的方法有3种,staticmethod装饰的静态方法,classmethod修饰的类方法,以及不带装饰器的普通方法(实例方法)。
staticmethod修饰的方法叫静态方法, 比较简单,它修饰的是可以直接通过类来调用的方法,这个方法不需要把self作为第一个参数,就像是把一个普通函数放到类里面一样。不仅类可以直接调用,实例也可以
class st:#其实静态方法用处不大,还不如直接把函数拿到类外面单独定义
@staticmethod
def print_str(s):
print(s)
st1=st()
st1.print_str('aaa')
>>aaa
st.print_str('bbb')
>>bbb
classmethod修饰的类方法还是很有用的,这种方法第一个参数是这个类本身,一般我们用cls表示,有了这个参数,我们就有了掌控整个类的能力,比如直接调用构造函数init()来创建实例
一个很有用的场景是:假如我们有个类Person,在构造函数里初始化用户的年龄,就像这样
p1 = Person(20)
这样很好了,但是可不可以通过生日也能创建一个person呢?就像这样:
p2 = Person.from_birth('1999')
classmethod 就能实现这个想法
from datetime import date
class Person:
def __init__(self, age):
self.age=age
@classmethod
def from_birth(cls, birth):
age=date.today().year - birth
return cls(age)
p1=Person(20)
p2=Person.from_birth(1999)
p1.age
>>20
p2.age
>>20
。
9. 字典的遍历和顺序问题
在python2 中,字典的序列是无序的,即字典里键实际的顺序和你插入的顺序不一样,但是在python3 中,
绝大多数情况下字典的顺序和插入的顺序是一致的,但要注意,在某些情况下,这个有序是不可靠的,所以,即使是python3,要确保字典有序,请使用OrderedDict来包装字典
capitals = {
'Gujarat' : 'Gandhinagar',
'Maharashtra' : 'Mumbai',
'Rajasthan' : 'Jaipur',
'Bihar' : 'Patna'
}
for c in capitals:
print(c)
# python2 里和插入顺序不同
Rajasthan
Maharashtra
Bihar
Gujarat
#python3 里和插入顺序相同
Gujarat
Maharashtra
Rajasthan
Bihar
# 使用OrderedDict确保字典有序
from collections import OrderedDict
capitals = OrderedDict([
('Gujarat', 'Gandhinagar'),
('Maharashtra', 'Mumbai'),
('Rajasthan', 'Jaipur'),
('Bihar', 'Patna')
])
字典的遍历有三种方式:
- 遍历key值
# 遍历key有两种方式:
a={'name':'jack', 'age':23}
for i in a:
print(i)
for i in a.keys():
print(i)
#输出:
name age
- 遍历value值
a={'name':'jack', 'age':23}
for i in a.values():
print(i)
#输出
jack 23
- 遍历 key, value 对
a={'name':'jack', 'age':23}
for k ,v in a.items():
print(k,v)
#输出
name jack
age 23
10. 变量的打包和解包
- list 变量的打包解包使用一个星号(*)
如果一个函数有不定个数的参数时要怎么写?比如写一个累加函数,这个函数可以接受任意多个输入参数,这个时候就要用到变量的打包
def mySum(*args):
sum = 0
for i in range(0, len(args)):
sum = sum + args[i]
return sum
print(mySum(1, 2, 3, 4, 5))
print(mySum(10, 20))
#输出
15
30
如果一个函数有很多个参数,我们可不可以一次性传入而不是一个个传入?这就用到变量的解包写法
def fun(a, b, c, d):
print(a, b, c, d)
my_list = [1, 2, 3, 4]
fun(*my_list)
#输出
(1, 2, 3, 4)
- dict变量的打包解包使用两个星号(**)
字典变量就是python里的关键字参数,比如:
# 这是解包
def person(name,age):
print('name is ' + name)
print('age is ' + age)
d= {'age':‘20’, 'name': 'jack'}
person(**d)
#输出:
name is jack
age is 20
# 这是打包
def person2(**kwargs):
for key in kwargs:
print("%s = %s" % (key, kwargs[key]))
persons(name='tom', addr='china')
#输出
name = tom
addr = china
11. 位运算
位运算就是把数字转成二进制形式再进行运算,相对于十进制的加减乘除,位运算符有以下几种:
(下表中变量 a 为 60,b 为 13,通过bin函数查看二进制:a = 0011 1100, b = 0000 1101)
看完了上面是不是觉得位运算也没啥用?其实不然,位运算在某些情况下能显著的提高代码效率
比如x&1等于1时x 为奇数,反之为偶数。再比如x>>1 右移1位表示除以2,左移一位表示乘以2
12. 分组统计
对于列表,有一个很常见的需求,就是列表中按照某个条件来统计相应的元素或元素数量,
比如一个包含很多人名的列表,现在需要统计每个名字长度下有哪些人,常见的写法是:
d=['jack', 'mayun','pony','lacky','john','steve','matthew']
dg = {}
for i in d:
if len(i) not in dg:
dg[len(i)]=[i]
else:
dg[len(i)].append(i)
#输出:
{4: ['jack', 'pony', 'john'], 5: ['mayun', 'lacky', 'steve'], 7: ['matthew']}
因为不知道元素长度是否已经在dg的key里面了,所以每次都要通过if len(i) not in dg检查。实际上python里字典有一个很好用的方法setdefault,就是为了解决这个问题的:
for i in d:
dg.setdefault(len(i), []).append(i)
#输出:
{5: ['mayun', 'steve', 'lacky'], 4: ['jack', 'pony', 'john'], 7: ['matthew']}