概念性问题
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:数据的转化
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: expression
– lambda 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],正数从小到大,负数从大到小,输出结果为[0,2,4,8,8,9,-2,-4,-4,-5,-20] (http://blog.lowid.me/2016/06/18/A-Python-interview-question-about-sorted-function/; https://www.v2ex.com/t/286691)
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收割机?这些面试题你必须掌握(基础篇)