Python面试题,拿offer必知必会(基础部分)

概念性问题

python2和python3区别

  • 字符编码: py3中默认字符编码是unicode;py2中默认字符编码是 ASCII,如果文件中出现了中文,需要在顶部加入coding声明#coding:utf8
  • 让用户输入:py3中直接使用input(); py2中需要使用raw_input()
  • range和xrange:py3中的range == py2中的 xrange, 返回类似迭代器的东西,节省内存空间
  • 语句变函数: py3中为print(), exec() 是一个方法,必须加上括号; py2中为print, exec
  • 数据传输: py3中socket传过来的数据是byte类型 / hashlib包update也需要传bytes类型的数据; py2中则可以直接传入str, e.g
# python3
import hashlib
m = hashlib.sha256()
m.update(b"Nobody inspects")

# python2
import hashlib
m = hashlib.md5()
m.update("Nobody inspects")

常见python标准库

  • math:数学相关的方法
  • datetime:基本日期时间
  • re:正则表达式相关操作
  • copy:深浅拷贝相关操作
  • sqlite3:为SQLite数据库提供的数据库接口
  • pickle/json:数据的转化

更多参阅官方文档: https://docs.python.org/3/library/index.html

Python的is和==

is是对比地址;==是对比值

列表去重

lst = [11,1,1,2,2,3,5,5]
lst = set(lst)
lst = list(lst)
print(lst)

字典操作

  • 删除字典某个键 – del
dct = {1:1, 2:2}
del dct[1]
print(dct)
  • 合并两个字典 – update()
dct = {1:1, 2:2}
dct1 = {3:3}
dct.update(dct1)
print(dct)
  • 对一个巨大的字典进行遍历
    py2使用iteritems() ;py3使用items()

https://docs.python.org/2/library/stdtypes.html#dict.iteritems
https://docs.python.org/3/library/stdtypes.html#dict.items

列出python中可变数据类型和不可变数据类型,并简述原理

可变类型(mutable):变量进行append、+=等这种操作后 == 改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。

  • list
  • dict
  • set
  • bytearray
  • user-defined classes (除非是特别定义的不可变)
a = [1,2]
b = [1,2]
print(id(a))
print(id(b))

不可变类型(immutable)改变了变量的值 == 新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象(一个地址), python的id() 方法让你明白

  • int
  • float
  • decimal
  • complex
  • bool
  • string
  • tuple
  • range
  • frozenset
  • bytes
a = 3
b = 3
print(id(a))
print(id(b)) # mem addr is same with a
a = 5
print(id(a))

boolx = True
print(id(boolx))
boolx = False
print(id(boolx))

int(“1.4”),int(1.4)输出结果?

  • int(“1.4”):ValueError: invalid literal for int() with base 10: ‘1.4’
  • int(1.4): 1

简述*args and **kwargs

  • 为了能让一个函数接受任意数量的位置参数*
  • 为了接受任意数量的关键字参数**
  • *参数只能出现在函数定义中最后一个位置参数后面,而**参数只能出现在最后一个参数
  • 解决的问题:构造一个可接受任意数量参数的函数

__new____init__的区别

  • __new__ 控制类实例创建过程时使用, 会在__init__ 调用之前调用, 调用这个方法之后,会返回一个实例 == __init__ 中的 self
  • __init__ 控制初始化一个类实例, 不会返回任何东西,它只负责初始化一个类实例

https://mail.python.org/pipermail/tutor/2008-April/061426.html

大文件的读取(也许10G,撑爆内存)

with open('x') as f:
    for line in f:
        print(line.replace('a', 'b'))

简述with原理

不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后已经关闭了打开的文件句柄。如果使用传统的 try/finally 范式,则要使用类似如下代码:

somefile = open(r'somefileName')
try:
    for line in somefile:
        print line
        # ...more code
finally:
    somefile.close()

context_expression 要返回一个上下文管理器对象,该对象并不赋值给 as 子句中的 target(s) ,如果指定了 as 子句的话,会将上下文管理器的 __enter__() 方法的返回值赋值给 target(s)。target(s) 可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)。

Python 对一些内建对象进行改进,加入了对上下文管理器的支持,可以用于 with 语句中,比如可以自动关闭文件、线程锁的自动获取和释放等

with context_expression [as target(s)]:
    with-body

https://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/

字典的拷贝

为什么不能用 dct1 = dct2 赋值?因为指向的是同一个内存地址
针对复合型对象而言,深浅拷贝会有如下区别:
- 浅拷贝:创建一个新复合型对象, 然后将所有原对象包含的其他对象的内存引用插入到新对象里面
- 深拷贝:创建一个新复合型对象, 将所有的原对象的的拷贝值插入到新对象中

迭代器和生成器

  • 可迭代对象:任何你可以用for ... in ... 的对象都是可迭代对象, list,strings, files, sockets…。 当你创建一个list的时候,你一个个的获取list里面的值,这就是可迭代对象
 mylist = [1, 2, 3]
 for i in mylist:
    print(i)
  • 迭代器:它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了_iter__next_()(python2中实现next())方法的对象都是迭代器, 有人需要的时候才给它生成值返回,没调用的时候就处于休眠状态等待下一次调用。
from itertools import count
counter = count(start=13)
next(counter) # 13
  • 生成器:迭代器的一种, 它不需要写__iter__()__next__() 方法,只需要一个yield关键字, 但是生成器只能迭代一次. 生成器只会在调用的时候产生值,他不会提前将值存储在内存中
mygenerator = (x*x for x in range(3))
for i in mygenerator:
    print(i)
  • 面试题:将列表生成式中[]改成() 之后数据结构是否改变? 答案:是,从列表变为生成器
L = [x*x for x in range(10)]
print(L) #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

g = (x*x for x in range(10)) 
print(g) #<generator object <genexpr> at 0x02FA6F90>

lambda函数

lambda 函数是一种快速定义单行的最小函数,省去了定义函数,只是一个表达式, 它将创建一个匿名函数, lambda arguments: expressionlambda x,y:x*y

func = lambda x,y:x*y
print(func(2,3)) # 6

a=(1,)b=(1),c=(“1”) 分别是什么类型的数据

(1,)– tuple; (“1”) – str; (1) – int

[1,2,3]+[4,5,6]的结果是多少?

两个列表相加 == extend
print([1,2,3]+[4,5,6]) # [1, 2, 3, 4, 5, 6]

python传参数是传值还是传址?

传址

  • 不可变类型(数值型、字符串、元组): 因变量不能修改,所以运算不会影响到变量自身
  • 可变类型(列表字典):函数体运算可能会更改传入的参数变量。

@staticmethod和@classmethod

  • @staticmethod:不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。
  • @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
class MyClass:
    def method(self):
        return 'instance method called', self

    @classmethod
    def classmethod(cls):
        return 'class method called', cls

    @staticmethod
    def staticmethod():
        return 'static method called'
a = MyClass()
\实例方法类方法静态方法
a = MyClass()a.foo(x)a.class_foo(x)a.static_foo(x)
MyClass不可用MyClass.class_foo(x)MyClass.static_foo(x)

单例模式

确保某一个类只有一个实例存在


class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  
        return cls._instance  

class MyClass(Singleton):  
    a = 1
'''
>>> one = MyClass()
>>> two = MyClass()
>>> one == two
True
>>> one is two
True
>>> id(one), id(two)
(4303862608, 4303862608)
'''

遇到bug如何处理

  • issue中查询是否有相似bug
  • assert / try-except / IDE单步调式
  • 框架可以查询源码或者查询官方文档

提高python运行效率的方法

  • 让关键代码依赖于外部包:你可以为紧急的任务使用C、C++或机器语言编写的外部包,这样可以提高应用程序的性能
  • 使用生成器,因为可以节约大量内存
  • 多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率
  • 使用较新的Python版本
  • 在排序时使用键(key)

try except else finally

  • try..except..else没有捕获到异常,执行else语句
  • try..except..finally不管是否捕获到异常,都执行finally语句

正则表达式匹配中,(.)和(.?)匹配区别

-(.*)是贪婪匹配,会把满足正则的尽可能多的往后匹配
-(.*?)是非贪婪匹配,会把满足正则的尽可能少匹配

正则re.complie作用

封装一个原本重复使用的正则表达式

prog = re.compile(pattern)
result = prog.match(string)

基础编码

统计字符串中某字符出现次数

num = 'Hello world'.count('l')  

用两种方法去空格

strx = "hello world ! this is Python"
strx.replace(" ", "")
print(strx)
strx = strx.split(' ')
strx = ''.join(strx)

函数内部修改全局变量(并不推荐这种做法)

var = 5
def func():
    global var
    var = 6
print(6)

a=”hello”和b=”世界”编码成bytes类型

a="hello"
b="世界"
a = b'hello'
b = b.encode(encoding='utf-8')

列表推导式求列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [i for i in a if i % 2 != 0]
print(b)

filter方法求出列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

a =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = filter(lambda x: x % 2 != 0, a)
for i in b:
    print(i)

排序

  • 嵌套元组排序从大到小, 按元组第二个字段排, 第二个字段相同则按名字
students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
print(sorted(students, key=lambda s:(s[1],s[2]), reverse=True))
  • 根据字符串长度排序
strx = ['hello', 'hi', 'yes', 'fine', 'thanks']
ret = sorted(strx, key=lambda ele:len(ele))
foo = [-5,8,0,4,9,-4,-20,-2,8,2,-4]
ret = sorted(foo, key=lambda ele: (ele<0, abs(ele)))
'''
两个比较条件:ele<0, abs(ele)
同时有个知识点: True>False
'''

请用datetime模块打印当前时间戳 “2018-04-01 11:38:54”并输出星期几

import datetime
current = "Date:%s  Week:%s" % (
        str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')),
        str(datetime.datetime.now().isoweekday()))
print(current)

生成0-100的随机数

import random
print(100*random.random()) #随即小数
print(random.choice(range(0,101)))
print(random.randint(1,100))

s=”info:xiaoZhang 33 shandong”,切分字符串输出[‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]

import re
s = "info:xiaoZhang 33 shandong"
s = re.split(r':| ', s)

s = “ajldjlajfdljfddd”,去重并从小到大排序输出”adfjl”

s = "ajldjlajfdljfddd"
lsts = list(set(s))
lsts.sort()
s = ''.join(lsts)

文章摘自微信公众号“派僧 (hellowoah)”抓住金九银十 | Pythoner成为offer收割机?这些面试题你必须掌握(基础篇)
这里写图片描述

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值