python 面试题总结

生成器函数

生成器有两种,分别是生成器函数和生成器表达式

生成器函数 - yield

  1. 定义 :含有yield语句的函数为生成器,该函数被调用会返回一个生成器对象。
  2. 表达式 : yield 表达式
  3. 用法 :
  • yield表达式用于def函数中,目的是将此函数作为生成器使用。
def myinteger(n):
  i = 0
  while i < n:
      yield i
      i += 1


for x in myinteger(3):
  print(x) #结果为012
  • yield用于生成数据,供迭代器的next()函数使用。

与return的区别

  • yield与return相似,后边跟返回值。但是不同的是:会保留执行状态,下次调用next()方法继续执行,从yield的下一条语句开始执行。如下代码所示:
#代码1
# 此示例示意用生成器函数生成一定范围内的自然数
def myinteger(n):
   i = 0
   while i < n:
       yield i
       i += 1
f = myinteger(3)
print(next(f)) #0
print(next(f)) #1
print(next(f)) #2
print(next(f)) #StopIteration
  • return 返回一个值之后,会直接终止程序的执行,终止当前生成器,如果执行next()会报错(若return之后无参数则不能与yield同时出现在一个函数中,否则为非法编程)。如下代码所示:
def myinteger(n):
   i = 0
   while i < n:
       yield i #此时生成器生成自然数0
       i += 1
       return i #终止生成器生成自然数,终止程序

f = myinteger(3)
print(next(f)) #0 (因生成器中生成自然数0,故可调用)
print(next(f)) #StopIteration 1 (生成器已被Return终止,故会报错)

生成器表达式

语法

(表达式 for 变量 in 可迭代对象 [if 真值表达式 ])
其中if表达式可以省略

作用

用推导式的形式生成一个新的生成器

L = [1,2,3,4]
gen = (i**2 for i in L) #生成新的生成器
L2 = iter(gen) #生成可迭代对象
print(next(L2)) #1
print(next(L2)) #4

正则表达式之match与search区别

match匹配从第一个字符串开始匹配到的内容

import re
obj = re.match(r'foo','foo,food on the table')
print(obj)#<_sre.SRE_Match object; span=(0, 3), match='foo'>
print(obj.group())#foo

search匹配第一个满足表达式的字符串

obj = re.search(r'foo','fo,food on the table')
print(obj)#<_sre.SRE_Match object; span=(3, 6), match='foo'>
print(obj.group())#foo
注意:两者返回的都是match对象,需要通过goup()方法获取匹配到的内容

正则表达式re.search和re.findall的区别

  1. re.findall(pattern,string)
    作用:根据正则表达式匹配目标字符串的内容
    返回值:满足正则表达式条件的所有内容组成的列表;如果正则表达式有子组,则返回子组列表
  2. re.search(pattern,string)
    返回值:匹配第一个满足表达式的match对象,需要通过goup()方法获取匹配到的字符串
    代码如下:
import re
l = re.findall(r'\S','Hi I like you')
print(l)#['H', 'i', 'I', 'l', 'i', 'k', 'e', 'y', 'o', 'u']

l = re.search(r'\S','Hi I like you')
print(l.group()) #H

map函数

  1. 概念:map(func,*iterable) 用函数和可迭代对象中的每个元素作为参数生成新的可迭代对象
  2. 用法
def power1(x):
    return x**2
l = map(power1,range(1,10))
for i in l:
    print(i,end=" ") #1 4 9 16 25 36 49 64 81

lambda 函数

  1. 语法:lamdda[参数1,参数2 …]:表达式
  2. 作用:创建一个匿名函数对象
  3. 用法:
myadd = lambda x,y:x+y
print("20+30=",myadd(20,30)) #20+30= 50
  1. filter函数。此时lambda函数用于指定过滤列表元素的条件。例如filter(lambda x: x % 3 == 0, [1, 2, 3])指定将列表[1,2,3]中能够被3整除的元素过滤出来,其结果是[3]。

  2. sorted函数。此时lambda函数用于指定对列表中所有元素进行排序的准则。例如sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))将列表[1, 2, 3, 4, 5, 6, 7, 8, 9]按照元素与5距离从小到大进行排序,其结果是[5, 4, 6, 3, 7, 2, 8, 1, 9]。

  3. map函数。此时lambda函数用于指定对列表中每一个元素的共同操作。例如map(lambda x: x+1, [1, 2,3])将列表[1, 2, 3]中的元素分别加1,其结果[2, 3, 4]。

  4. reduce函数。此时lambda函数用于指定列表中两两相邻元素的结合条件。例如reduce(lambda a, b: ‘{}, {}’.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])将列表 [1, 2, 3, 4, 5, 6, 7, 8, 9]中的元素从左往右两两以逗号分隔的字符的形式依次结合起来,其结果是’1, 2, 3, 4, 5, 6, 7, 8, 9’。

原文:https://blog.csdn.net/zjuxsl/article/details/79437563

深拷贝与浅拷贝

浅拷贝

浅拷贝是指创建一个新的对象,其内容是对原对象的引用。(即只拷贝组合对象,不拷贝子对象)
从下方例子可以看出,a和b指向内存中不同的list对象,但他们的元素指向相同的int对象,即子对象。

>>> a = [1,2,3]
>>> b = list(a)
>>> b
[1, 2, 3]
>>> id(a)
139644786708168
>>> id(b)
139644786741704
>>> for x,y in zip(a,b):
...     print(id(x),id(y))
... 
10919424 10919424
10919456 10919456
10919488 10919488

浅拷贝的特点:两对象内存地址不同,内容相同。
浅拷贝的操作:切片操作,工厂函数,对象的copy()方法,copy模块中的copy()函数。

深拷贝

深拷贝是指拷贝一个新对象,递归拷贝原对象中的子对象
深拷贝只有一个方法:copy模块中的deepcopy()函数

当子对象为不可变类型时(int,str,float,tuple)

>>> a = [1,2,3]
>>> import copy
>>> b = copy.copy(a)
>>> c = copy.deepcopy(a)
>>> id(b)
139644786771144
>>> id(c)
139644786741704
>>> for x,y in zip(a,b):
...     print(id(x),id(y))
... 
10919424 10919424
10919456 10919456
10919488 10919488
>>> for x,y in zip(a,c):
...     print(id(x),id(y))
... 
10919424 10919424
10919456 10919456
10919488 10919488
>>> b[0] = 10
>>> b
[10, 2, 3]
>>> a
[1, 2, 3]
>>> c[0] = 11
>>> c
[11, 2, 3]
>>> a
[1, 2, 3]
>>> for x,y in zip(a,c):
...     print(id(x),id(y))
... 
10919424 10919744
10919456 10919456
10919488 10919488
>>> for x,y in zip(a,b):
...     print(id(x),id(y))
... 
10919424 10919712
10919456 10919456
10919488 10919488

当对b[0]进行赋值时,因为int为不可变对象,所以需要开辟另一块内存空间创建一个新对象并进行初始化,使b[0]指向该对象。

当子对象为可变对象时(list,dict)

>>> a = [[1,2],[2,3]]
>>> b = copy.copy(a)
>>> c = copy.deepcopy(a)
>>> for x,y in zip(a,b):
...     print(id(x),id(y))
... 
139644786771464 139644786771464
139644786771400 139644786771400
>>> for x,y in zip(a,c):
...     print(id(x),id(c))
... 
139644786771464 139644786771144
139644786771400 139644786771144
>>> id(c)
139644786771144

总结:

  1. 赋值:拷贝生成的对象与原对象内存地址相同,内容也相同,即共用一个内存空间
  2. 浅拷贝:拷贝生成的对象内存地址相同,与原对象共享内存中的子对象
  3. 深拷贝: 生成新的组合对象,同时递归地拷贝所有子对象。新的组合对象与原对象没有任何关联。虽然会共享不可变子对象,但仍然相互独立。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值