python基础面试题(五)

1.以下代码输出是什么,请给出答案并解释

def multipliers():
		return [lambda x:x*i for i in range(4)] 
		
print([m(2) for m in multipliers()])

# 答案:
	[6,6,6,6]
	

这个问题涉及到了Python的闭包及延时绑定的知识(Python作用域)。

在Python核心编程里,闭包的定义如下:

如果在一个内部函数里,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认定是闭包。

总结为三点:

  • 1、是一个内嵌函数

  • 2、对外部函数变量引用

  • 3、外部函数返回内嵌函数

上面的那道题,可以写成这样:

def func():
    fun_list = []
    for i in range(4):
        def foo(x):
            return x*i
        fun_list.append(foo)
    return fun_list
for m in func():
  print(m(2))

当我们执行 m(2) 时,运行到foo()内部函数,发现变量 i 并不是foo()中的变量,于是就到外部函数func中寻找变量 i ,但此时外部的 for 已经循环完毕,最后的 i =3 。所以,每次

执行m(2),i 的值都是 3 ,因此,最终结果会是 [6, 6, 6, 6] 。

当在foo()中添加 i=i 后,即:


def func():
    fun_list = []
    for i in range(4):
        def foo(x, i=i):
            return x*i
        fun_list.append(foo)
    return fun_list
for m in func():
    print(m(2))
    
'''
执行结果:
0
2
4
6
'''
闭包函数延迟绑定问题。
# 所以最终我们可以修改 multipliers 的定义来产生期望的结果
def multipliers():
		return [lambda x, i=i:x*i for i in range(4)] 
print([m(2) for m in multipliers()])

'''
[0, 2, 4, 6]
'''

2. 提高python运行效率的方法

1、使用生成器,因为可以节约大量内存
2、循环代码优化,避免过多重复代码的执行
3、核心模块用Cython PyPy等,提高效率
4、多进程、多线程、协程
5、多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率

3.有一个数据结构如下所示,请编写⼀个函数从该结构数据中返回由指定的字段和对应的值组成的字典。如果指定字段不存在,则跳过该字段。

data:{
    "time":"2016-08-05T13:13:05",
    "some_id":"ID1234",
    "grp1":{"fld1":1, "fld2":2,},
    "xxx2":{"fld3":0, "fld4":0.4,},
		"fld6":11,
		"fld7": 7,
		"fld46":8
}

# fields:由"|"连接的以 fld 开头的字符串, 如 fld2|fld7|fld29
# 答案一:
def select(data, fields):
    result = {}
    field_lst = fields.split('|')
    for key in data:
        if key in field_lst:
            result[key] = data[key]
        elif type(data[key]) == dict:
            res = select(data[key], fields)
            result.update(res)
    return result


data = {"time": "2016-08-05T13:13:05",
        "some_id": "ID1234",
        "grp1": {"fld1": 1, "fld2": 2},
        "xxx2": {"fld3": 0, "fld5": 0.4},
        "fld6": 11,
        "fld7": 7,
        "fld46": 8}
fields = 'fld2|fld3|fld7|fld19'
print(select(data, fields))

# 答案二:
def select(data,fields,result = {}):
    field_lst = fields.split('|')
    for key in data:
        if key in field_lst:
            result[key] = data[key]
        elif type(data[key]) == dict:
            select(data[key], fields)
    return result
    
data={"time":"2016-08-05T13:13:05",
    "some_id":"ID1234",
    "grp1":{ "fld1":1,"fld2":2},
    "xxx2":{ "fld3":0,"fld5":0.4},
    "fld6":11,
    "fld7":7,
    "fld46":8}
fields = 'fld2|fld3|fld7|fld19'
select(data,fields)
print(select(data,fields))

4. Python函数调用的时候参数的传递方式是值传递还是引用传递?

Python的参数传递有:位置参数、默认参数、可变参数、关键字参数。
函数的传值到底是值传递还是引用传递,要分情况:

  • 不可变参数用值传递:
    像整数和字符串这样的不可变对象,是通过拷贝进行传递的,因为你无论如何都不可能在原处改变
  • 可变参数是引用传递的:
    比如像列表,字典这样的对象是通过引用传递、和C语言里面的用指针传递数组很相似,可变对象能在函数内部改变。

5. 简述mysql和redis区别

redis:内存型非关系数据库,数据保存在内存中,速度快
mysql:关系型数据库,数据保存在磁盘中,检索的话,会有一定的lo操作,访问速度相对慢

6. list=[2,3,5,4,9,6],从小到大排序,不许用sort,输出[2,3,4,5,6,9]

利用min()方法求出最小值,原列表删除最小值,新列表加入最小值,递归调用获取最小值的函数,反复操作:


ls = [2,3,5,4,9,6]
new_ls=[]
def get_min(ls):
    m = min(ls)
    ls.remove(m)
    new_ls.append(m)
    if len(ls)>0:
        get_min(ls)
    return new_ls

new_ls = get_min(ls)
print(new_ls)
# [2, 3, 4, 5, 6, 9]

7. 写一个单例模式

因为创建对象时_new_方法执行,并且必须return返回实例化出来的对象,所以需要判断cls._instance是否存在,不存在的话就创建对象,存在的话就返回该对象,来保证只有一个实例对象存在(单列),打印ID,值一样,说明对象同一个


class dan(object):
    __instance = None
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
             cls.__instance = object.__new__(cls)
        return cls.__instance

a = dan(1,2)
b = dan(3,4)
print(id(a))
print(id(b))
'''
执行结果:
1544211957520
1544211957520
'''

8.map函数和reduce函数用法区别?

①从参数方面来讲:
map()包含两个参数,第一个参数是一个函数,第二个是序列(列表 或元组)。其中,函数(即 map
的第一个参数位置的函数)可以接收一个或多个参数。
reduce()第一个参数是函数,第二个是序列(列表或元组)。但是,其函数必须接收两个参数。

②从对传进去的数值作用来讲:
map()是将传入的函数依次作用到序列的每个元素,每个元素都是独自被函数“作用”一次 。
reduce()是将传人的函数作用在序列的第一个元素得到结果后,把这个结果继续与下一个元素作用
(累积计算)。

9. 列出常见的状态码和意义

200 OK 请求正常处理完毕
204 No Content 请求成功处理,没有实体的主体返回
206 Partial Content GET范围请求已成功处理
301 Moved Permanently永久重定向,资源已永久分配新URI
302 Found 临时重定向,资源已临时分配新URI
303 See Other 临时重定向,期望使用GET定向获取
304 Not Modified 发送的附带条件请求未满足
307 Temporary Redirect 临时重定向,POST不会变成GET
400 Bad Request 请求报文语法错误或参数错误
401 Unauthorized 需要通过HTTP认证,或认证失败
403 Forbidden请求资源被拒绝
404 Not Found 无法找到请求资源(服务器无理由拒绝)
500 Internal Server Error服务器故障或Web应用故障
503 Service Unavailable服务器超负载或停机维护

10.什么是回调函数?

百度百科说:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

通俗理解就是:把一个函数作为参数传递给另一个函数,第一个函数被称为回调函数。
回调函数是把函数的地址作为参数传递给另一个函数,将整个函数当作一个对象,赋值给调用的函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰履踏青云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值