问题一:以下的代码的输出将是什么? 说出你的答案并解释。
class Parent(object):
x = 1
class Child1(Parent):
pass
class Child2(Parent):
pass
print Parent.x, Child1.x, Child2.x
Child1.x = 2
print Parent.x, Child1.x, Child2.x
Parent.x = 3
print Parent.x, Child1.x, Child2.x
答案
以上代码的输出是:
1 1 1
1 2 1
3 2 3
使你困惑或是惊奇的是关于最后一行的输出是 3 2 3 而不是 3 2 1。为什么改变了 Parent.x 的值还会改变 Child2.x 的值,但是同时 Child1.x 值却没有改变?
这个答案的关键是,在 Python 中,类变量在内部是作为字典处理的。如果一个变量的名字没有在当前类的字典中发现,将搜索祖先类(比如父类)直到被引用的变量名被找到(如果这个被引用的变量名既没有在自己所在的类又没有在祖先类中找到,会引发一个 AttributeError 异常 )。
因此,在父类中设置 x = 1 会使得类变量 X 在引用该类和其任何子类中的值为 1。这就是因为第一个 print 语句的输出是 1 1 1。
随后,如果任何它的子类重写了该值(例如,我们执行语句 Child1.x = 2),然后,该值仅仅在子类中被改变。这就是为什么第二个 print 语句的输出是 1 2 1。
最后,如果该值在父类中被改变(例如,我们执行语句 Parent.x = 3),这个改变会影响到任何未重写该值的子类当中的值(在这个示例中被影响的子类是 Child2)。这就是为什么第三个 print 输出是 3 2 3。
问题二:以下的代码的输出将是什么? 说出你的答案并解释?
def div1(x,y):
print("%s/%s = %s" % (x, y, x/y))
def div2(x,y):
print("%s//%s = %s" % (x, y, x//y))
div1(5,2)
div1(5.,2)
div2(5,2)
div2(5.,2.)
答案
这个答案实际依赖于你使用的是 Python 2 还是 Python 3。
在 Python 3 中,期望的输出是:
5/2 = 2.5
5.0/2 = 2.5
5//2 = 2
5.0//2.0 = 2.0
在 Python 2 中,尽管如此,以上代码的输出将是:
5/2 = 2
5.0/2 = 2.5
5//2 = 2
5.0//2.0 = 2.0
默认,如果两个操作数都是整数,Python 2 自动执行整型计算。结果,5/2 值为 2,然而 5./2 值为 ```2.5``。
注意,尽管如此,你可以在 Python 2 中重载这一行为(比如达到你想在 Python 3 中的同样结果),通过添加以下导入:
from __future__ import division
也需要注意的是“双划线”(//)操作符将一直执行整除,而不管操作数的类型,这就是为什么 5.0//2.0 值为 2.0。
注: 在 Python 3 中,/ 操作符是做浮点除法,而 // 是做整除(即商没有余数,比如 10 // 3 其结果就为 3,余数会被截除掉,而 (-7) // 3 的结果却是 -3。这个算法与其它很多编程语言不一样,需要注意,它们的整除运算会向0的方向取值。而在 Python 2 中,/ 就是整除,即和 Python 3 中的 // 操作符一样,)
问题三:以下代码将输出什么?
list = ['a', 'b', 'c', 'd', 'e']
print list[10:]
答案
以上代码将输出 [],并且不会导致一个 IndexError。
正如人们所期望的,试图访问一个超过列表索引值的成员将导致 IndexError(比如访问以上列表的 list[10])。尽管如此,试图访问一个列表的以超出列表成员数作为开始索引的切片将不会导致 IndexError,并且将仅仅返回一个空列表。
一个讨厌的小问题是它会导致出现 bug ,并且这个问题是难以追踪的,因为它在运行时不会引发错误。
问题四:以下的代码的输出将是什么? 说出你的答案并解释?
def multipliers():
return [lambda x : i * x for i in range(4)]
print [m(2) for m in multipliers()]
你将如何修改 multipliers 的定义来产生期望的结果
答案
以上代码的输出是 [6, 6, 6, 6] (而不是 [0, 2, 4, 6])。
这个的原因是 Python 的闭包的后期绑定导致的 late binding,这意味着在闭包中的变量是在内部函数被调用的时候被查找。所以结果是,当任何 multipliers() 返回的函数被调用,在那时,i 的值是在它被调用时的周围作用域中查找,到那时,无论哪个返回的函数被调用,for 循环都已经完成了,i 最后的值是 3,因此,每个返回的函数 multiplies 的值都是 3。因此一个等于 2 的值被传递进以上代码,它们将返回一个值 6 (比如: 3 x 2)。
(顺便说下,正如在 The Hitchhiker’s Guide to Python 中指出的,这里有一点普遍的误解,是关于 lambda 表达式的一些东西。一个 lambda 表达式创建的函数不是特殊的,和使用一个普通的 def 创建的函数展示的表现是一样的。)
这里有两种方法解决这个问题。
最普遍的解决方案是创建一个闭包,通过使用默认参数立即绑定它的参数。例如:
def multipliers():
return [lambda x, i=i : i * x for i in range(4)]
另外一个选择是,你可以使用 functools.partial 函数:
from functools import partial
from operator import mul
def multipliers():
return [partial(mul, i) for i in range(4)]
问题五:以下的代码的输出将是什么? 说出你的答案并解释?
def extendList(val, list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')
print "list1 = %s" % list1
print "list2 = %s" % list2
print "list3 = %s" % list3
你将如何修改 extendList 的定义来产生期望的结果
以上代码的输出为:
list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']
许多人会错误的认为 list1 应该等于 [10] 以及 list3 应该等于 ['a']。认为 list 的参数会在 extendList 每次被调用的时候会被设置成它的默认值 []。
尽管如此,实际发生的事情是,新的默认列表仅仅只在函数被定义时创建一次。随后当 extendList 没有被指定的列表参数调用的时候,其使用的是同一个列表。这就是为什么当函数被定义的时候,表达式是用默认参数被计算,而不是它被调用的时候。
因此,list1 和 list3 是操作的相同的列表。而 ````list2是操作的它创建的独立的列表(通过传递它自己的空列表作为list``` 参数的值)。
extendList 函数的定义可以做如下修改,但,当没有新的 list 参数被指定的时候,会总是开始一个新列表,这更加可能是一直期望的行为。
def extendList(val, list=None):
if list is None:
list = []
list.append(val)
return list
使用这个改进的实现,输出将是:
list1 = [10]
list2 = [123]
list3 = ['a']
最近,整理了一些Python常见的面试题目,语言是一种工具,但是多角度的了解工具能帮助我们更好的工作。
从很多国内网站以及一些国外论坛翻译过来的,虽然本文标注为"原创",但是仅仅是自己日常整理的材料,文章后面会附上参考来源。
第一部分:
简易/中等
什么是Python装饰器,如何使用?
你会如何设置很多项目,其中每一个使用Python的不同版本和第三方库?
什么是PEP8和你是如何遵循它的规范?
参数是如何传递的 - 传值还是传引用? (容易,但又不那么容易,不确定是否能清楚地回答这个问题)
什么是列表解析、字典解析?举个例子
请用三种不同的方法完成"提取列表中每三个项目"?
你知道列表和元组之间的区别么?举个例子?
你知道range和xrange之间的区别? 针对python2.x版本
谈谈Python2.x和3.x之间的一些区别?
with语句及其用法?
如何避免对模块或方法的重复import?
为什么GIL重要?
什么是“特殊方法"(如<foo>)?它们如何工作的?
python中什么是一级对象(first-class objects)? 如何将函数作为一级对象操纵呢?
"class Foo" 和 "class Foo(object)"之间的区别?
棘手的
Python中,如何读取大小为8GB的文件? (即python如何读取大文件)
你为何喜欢Python,又有哪些不喜欢的部分?
不能借助内置方法如string.atoi或者int(),能否将ASCII字符转换为整数?
主观的
你用制表符还是空格,哪些是更好?
其他:(不断扩充.......自己整理......)
列表与元组的区别是什么.分别在什么情况下使用?
谈谈你用过的Python库?
对Python中装饰器的认识?
Python中文件/模块/包之间的关系?包文件夹下__init__.py作用是什么?
Python是如何进行内存管理的?
第二部分:基本数据结构
第三部分:
下面的题目看看即可。。。
1:Python如何实现单例模式? 请参考:http://blog.****.Net/ghostfromheaven/article/details/7671853
2:什么是lambda函数?
Python允许你定义一种单行的小函数。定义lambda函数的形式如下:labmda 参数:表达式lambda函数默认返回表达式的值。你也可以将其赋值给一个变量。lambda函数可以接受任意个参数,包括可选参数,但是表达式只有一个:
>>> g = lambda x, y: x*y
>>> g(3,4)
12
>>> g = lambda x, y=0, z=0: x+y+z
>>> g(1)
1
>>> g(3, 4, 7)
14
也能够直接使用lambda函数,不把它赋值给变量:
>>> (lambda x,y=0,z=0:x+y+z)(3,5,6)
14
如果你的函数非常简单,只有一个表达式,不包含命令,可以考虑lambda函数。否则,你还是定义函数才对,毕竟函数没有这么多限制。
3:Python是如何进行类型转换的?
Python提供了将变量或值从一种类型转换成另一种类型的内置函数。int函数能够将符合数学格式数字型字符串转换成整数。否则,返回错误信息。
>>> int(”34″)
34
>>> int(”1234ab”) #不能转换成整数
ValueError: invalid literal for int(): 1234ab
函数int也能够把浮点数转换成整数,但浮点数的小数部分被截去。
>>> int(34.1234)
34
>>> int(-2.46)
-2
函数°oat将整数和字符串转换成浮点数:
>>> float(”12″)
12.0
>>> float(”1.111111″)
1.111111
函数str将数字转换成字符:
>>> str(98)
‘98′
>>> str(”76.765″)
‘76.765′
整数1和浮点数1.0在python中是不同的。虽然它们的值相等的,但却属于不同的类型。这两个数在计算机的存储形式也是不一样。
4:Python如何定义一个函数
函数的定义形式如
下:
def <name>(arg1, arg2,… argN):
< statements>
函数的名字也必须以字母开头,可以包括下划线“ ”,但不能把Python的
关键字定义成函数的名字。函数内的语句数量是任意的,每个语句至少有
一个空格的缩进,以表示此语句属于这个函数的。缩进结束的地方,函数
自然结束。
下面定义了一个两个数相加的函数:
>>> def add(p1, p2):
print p1, “+”, p2, “=”, p1+p2
>>> add(1, 2)
1 + 2 = 3
函数的目的是把一些复杂的操作隐藏,来简化程序的结构,使其容易
阅读。函数在调用前,必须先定义。也可以在一个函数内部定义函数,内
部函数只有在外部函数调用时才能够被执行。程序调用函数时,转到函数
内部执行函数内部的语句,函数执行完毕后,返回到它离开程序的地方,
执行程序的下一条语句。
5:Python是如何进行内存管理的?
Python的内存管理是由Python得解释器负责的,开发人员可以从内存管理事务中解放出来,致力于应用程序的开发,这样就使得开发的程序错误更少,程序更健壮,开发周期更短
6:如何反序的迭代一个序列?how do I iterate over a sequence in reverse order
如果是一个list, 最快的解决方案是:
list.reverse()
try:
for x in list:
“do something with x”
finally:
list.reverse()
如果不是list, 最通用但是稍慢的解决方案是:
for i in range(len(sequence)-1, -1, -1):
x = sequence[i]
< do something with x>
7:Python里面如何实现tuple和list的转换?
函数tuple(seq)可以把所有可迭代的(iterable)序列转换成一个tuple, 元素不变,排序也不变。
例如,tuple([1,2,3])返回(1,2,3), tuple(’abc’)返回(’a’.’b',’c').如果参数已经是一个tuple的话,函数不做任何拷贝而直接返回原来的对象,所以在不确定对象是不是tuple的时候来调用tuple()函数也不是很耗费的。
函数list(seq)可以把所有的序列和可迭代的对象转换成一个list,元素不变,排序也不变。
例如 list([1,2,3])返回(1,2,3), list(’abc’)返回['a', 'b', 'c']。如果参数是一个list, 她会像set[:]一样做一个拷贝
8:Python面试题:请写出一段Python代码实现删除一个list里面的重复元素
可以先把list重新排序,然后从list的最后开始扫描,代码如下:
if List:
List.sort()
last = List[-1]
for i in range(len(List)-2, -1, -1):
if last==List[i]: del List[i]
else: last=List[i]
9:Python文件操作的面试题
1. 如何用Python删除一个文件?
使用os.remove(filename)或者os.unlink(filename);
2. Python如何copy一个文件?
shutil模块有一个copyfile函数可以实现文件拷贝
10:Python里面如何生成随机数?
标准库random实现了一个随机数生成器,实例代码如下:
import random
random.random()
它会返回一个随机的0和1之间的浮点数
11:如何用Python来发送邮件?
可以使用smtplib标准库。
以下代码可以在支持SMTP监听器的服务器上执行。
import sys, smtplib
fromaddr = raw_input(”From: “)
toaddrs = raw_input(”To: “).split(’,')
print “Enter message, end with ^D:”
msg = ”
while 1:
line = sys.stdin.readline()
if not line:
break
msg = msg + line
# 发送邮件部分
server = smtplib.SMTP(’localhost’)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
12:Python里面如何拷贝一个对象?
一般来说可以使用copy.copy()方法或者copy.deepcopy()方法,几乎所有的对象都可以被拷贝
一些对象可以更容易的拷贝,Dictionaries有一个copy方法:
newdict = olddict.copy()
13:有没有一个工具可以帮助查找python的bug和进行静态的代码分析?
有,PyChecker是一个python代码的静态分析工具,它可以帮助查找python代码的bug, 会对代码的复杂度和格式提出警告
Pylint是另外一个工具可以进行coding standard检查。
14:如何在一个function里面设置一个全局的变量?
解决方法是在function的开始插入一个global声明:
def f()
global x
14:有两个序列a,b,大小都为n,序列元素的值任意整形数,无序;要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
1. 将两序列合并为一个序列,并排序,为序列Source
2. 拿出最大元素Big,次大的元素Small
3. 在余下的序列S[:-2]进行平分,得到序列max,min
4. 将Small加到max序列,将Big加大min序列,重新计算新序列和,和大的为max,小的为min。
Python代码
def mean( sorted_list ):
if not sorted_list:
return (([],[]))
big = sorted_list[-1]
small = sorted_list[-2]
big_list, small_list = mean(sorted_list[:-2])
big_list.append(small)
small_list.append(big)
big_list_sum = sum(big_list)
small_list_sum = sum(small_list)
if big_list_sum > small_list_sum:
return ( (big_list, small_list))
else:
return (( small_list, big_list))
tests = [ [1,2,3,4,5,6,700,800],
[10001,10000,100,90,50,1],
range(1, 11),
[12312, 12311, 232, 210, 30, 29, 3, 2, 1, 1]
]
for l in tests:
l.sort()
print “Source List:\t”, l
l1,l2 = mean(l)
print “Result List:\t”, l1, l2
print “Distance:\t”, abs(sum(l1)-sum(l2))
print ‘-*’*40
输出结果
Python代码
Source List: [1, 2, 3, 4, 5, 6, 700, 800]
Result List: [1, 4, 5, 800] [2, 3, 6, 700]
Distance: 99
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Source List: [1, 50, 90, 100, 10000, 10001]
Result List: [50, 90, 10000] [1, 100, 10001]
Distance: 38
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Source List: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Result List: [2, 3, 6, 7, 10] [1, 4, 5, 8, 9]
Distance: 1
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Source List: [1, 1, 2, 3, 29, 30, 210, 232, 12311, 12312]
Result List: [1, 3, 29, 232, 12311] [1, 2, 30, 210, 12312]
Distance: 21
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
15:用Python匹配HTML tag的时候,<.*>和<.*?>有什么区别?
当重复匹配一个正则表达式时候, 例如<.*>, 当程序执行匹配的时候,会返回最大的匹配值
例如:
import re
s = ‘<html><head><title>Title</title>’
print(re.match(’<.*>’, s).group())
会返回一个匹配<html><head><title>Title</title>而不是<html>
而
import re
s = ‘<html><head><title>Title</title>’
print(re.match(’<.*?>’, s).group())
则会返回<html>
<.*>这种匹配称作贪心匹配 <.*?>称作非贪心匹配
16:Python里面search()和match()的区别?
match()函数只检测RE是不是在string的开始位置匹配, search()会扫描整个string查找匹配, 也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none
例如:
print(re.match(’super’, ’superstition’).span())会返回(0, 5)
而print(re.match(’super’, ‘insuperable’))则返回None
search()会扫描整个字符串并返回第一个成功的匹配
例如:print(re.search(’super’, ’superstition’).span())返回(0, 5)
print(re.search(’super’, ‘insuperable’).span())返回(2, 7)
17:如何用Python来进行查询和替换一个文本字符串?
可以使用sub()方法来进行查询和替换,sub方法的格式为:sub(replacement, string[, count=0])
replacement是被替换成的文本
string是需要被替换的文本
count是一个可选参数,指最大被替换的数量
例子:
import re
p = re.compile(’(blue|white|red)’)
print(p.sub(’colour’,'blue socks and red shoes’))
print(p.sub(’colour’,'blue socks and red shoes’, count=1))
输出:
colour socks and colour shoes
colour socks and red shoes
subn()方法执行的效果跟sub()一样,不过它会返回一个二维数组,包括替换后的新的字符串和总共替换的数量
例如:
import re
p = re.compile(’(blue|white|red)’)
print(p.subn(’colour’,'blue socks and red shoes’))
print(p.subn(’colour’,'blue socks and red shoes’, count=1))
输出
(’colour socks and colour shoes’, 2)
(’colour socks and red shoes’, 1)
18:介绍一下except的用法和作用?
Python的except用来捕获所有异常, 因为Python里面的每次错误都会抛出 一个异常,所以每个程序的错误都被当作一个运行时错误。
一下是使用except的一个例子:
try:
foo = opne(”file”) #open被错写为opne
except:
sys.exit(”could not open file!”)
因为这个错误是由于open被拼写成opne而造成的,然后被except捕获,所以debug程序的时候很容易不知道出了什么问题
下面这个例子更好点:
try:
foo = opne(”file”) # 这时候except只捕获IOError
except IOError:
sys.exit(”could not open file”)
19:Python中pass语句的作用是什么?
pass语句什么也不做,一般作为占位符或者创建占位程序,pass语句不会执行任何操作,比如:
while False:
pass
pass通常用来创建一个最简单的类:
class MyEmptyClass:
pass
pass在软件设计阶段也经常用来作为TODO,提醒实现相应的实现,比如:
def initlog(*args):
pass #please implement this
20:介绍一下Python下range()函数的用法?
如果需要迭代一个数字序列的话,可以使用range()函数,range()函数可以生成等差级数。
如例:
for i in range(5)
print(i)
这段代码将输出0, 1, 2, 3, 4五个数字
range(10)会产生10个值, 也可以让range()从另外一个数字开始,或者定义一个不同的增量,甚至是负数增量
range(5, 10)从5到9的五个数字
range(0, 10, 3) 增量为三, 包括0,3,6,9四个数字
range(-10, -100, -30) 增量为-30, 包括-10, -40, -70
可以一起使用range()和len()来迭代一个索引序列
例如:
a = ['Nina', 'Jim', 'Rainman', 'Hello']
for i in range(len(a)):
print(i, a[i])
1. 如何用Python删除一个文件?
使用os.remove(filename)或者os.unlink(filename);
2. Python如何copy一个文件?
shutil模块有一个copyfile函数可以实现文件拷贝
1. 如何用Python删除一个文件?
使用os.remove(filename)或者os.unlink(filename);
2. Python如何copy一个文件?
shutil模块有一个copyfile函数可以实现文件拷贝
3. python程序中文输出问题怎么解决?
方法一:
用encode和decode
如:
import os.path
import xlrd,sys
Filename=’/home/tom/Desktop/1234.xls’
if not os.path.isfile(Filename):
raise NameError,”%s is not a valid filename”%Filename
bk=xlrd.open_workbook(Filename)
shxrange=range(bk.nsheets)
print shxrange
for x in shxrange:
p=bk.sheets()[x].name.encode(‘utf-8′)
print p.decode(‘utf-8′)方法二:
在文件开头加上
reload(sys)
sys.setdefaultencoding(‘utf8′)这2行,再试着运行一下
Python里面如何实现tuple和list的转换?
函数tuple(seq)可以把所有可迭代的(iterable)序列转换成一个tuple, 元素不变,排序也不变。例如,tuple([1,2,3])返回(1,2,3), tuple(‘abc’)返回(‘a’.'b’,'c’).如果参数已经是一个tuple的话,函数不做任何拷贝而直接返回原来的对象,所以在不确定对象是不是tuple的时候来调用tuple()函数也不是很耗费的。函数list(seq)可以把所有的序列和可迭代的对象转换成一个list,元素不变,排序也不变。例如 list([1,2,3])返回(1,2,3), list(‘abc’)返回['a', 'b', 'c']。如果参数是一个list, 她会像set[:]一样做一个拷贝
如何反序的迭代一个序列?how do I iterate over a sequence in reverse order
如果是一个list, 最快的解决方案是:
list.reverse()
try:
for x in list:
“do something with x”
finally:
list.reverse()
如果不是list, 最通用但是稍慢的解决方案是:
for i in range(len(sequence)-1, -1, -1):
x = sequence[i]
Python是如何进行类型转换的?
Python提供了将变量或值从一种类型转换成另一种类型的内置函数。int函数能够将符合数学格式数字型字符串转换成整数。否则,返回错误信息。
>>> int(“34″)
34
>>> int(“1234ab”) #不能转换成整数
ValueError: invalid literal for int(): 1234ab
函数int也能够把浮点数转换成整数,但浮点数的小数部分被截去。
>>> int(34.1234)
34
>>> int(-2.46)
-2
函数°oat将整数和字符串转换成浮点数:
>>> float(“12″)
12.0
>>> float(“1.111111″)
1.111111
函数str将数字转换成字符:
>>> str(98)
’98′
>>> str(“76.765″)
’76.765′
整数1和浮点数1.0在python中是不同的。虽然它们的值相等的,但却属于不同的类型。这两个数在计算机的存储形式也是不一样。
用Python匹配HTML tag的时候,<.*>和<.*?>有什么区别?
当重复匹配一个正则表达式时候, 例如, 当程序执行匹配的时候,会返回最大的匹配值
例如:
import re
s = ‘Title’
print(re.match(‘’, s).group())会返回一个匹配Title而不是、
import re
s = ‘Title’
print(re.match(‘’, s).group())则会返回这种匹配称作贪心匹配 称作非贪心匹配
Python的两道面试题
有没有一个工具可以帮助查找python的bug和进行静态的代码分析?有,PyChecker是一个python代码的静态分析工具,它可以帮助查找python代码的bug, 会对代码的复杂度和格式提出警告
Pylint是另外一个工具可以进行coding standard检查。
2. 如何在一个function里面设置一个全局的变量?解决方法是在function的开始插入一个global声明:
def f()
global x
请用Python写一个获取用户输入数字,并根据数字大小输出不同信息的脚本
代码如下(Python 3.0 下调试通过)
x = int(input(“Please enter an integer:”))
if x < 0:
x = 0
print (‘Negative changed to zero’)
elif x == 0:
print (‘Zero’)
elif x == 1:
print (‘Single’)
else:
print (‘More’)
Python面试题:Python里面如何生成随机数?
标准库random实现了一个随机数生成器,实例代码如下:
import random
random.random()
它会返回一个随机的0和1之间的浮点数
华为python面试题
有两个序列a,b,大小都为n,序列元素的值任意整形数,无序;
要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
有两个序列a,b,大小都为n,序列元素的值任意整形数,无序;
要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
1. 将两序列合并为一个序列,并排序,为序列Source
2. 拿出最大元素Big,次大的元素Small
3. 在余下的序列S[:-2]进行平分,得到序列max,min
4. 将Small加到max序列,将Big加大min序列,重新计算新序列和,和大的为max,小的为min。
Python代码
def mean( sorted_list ):
if not sorted_list:
return (([],[]))
big = sorted_list[-1]
small = sorted_list[-2]
big_list, small_list = mean(sorted_list[:-2])
big_list.append(small)
small_list.append(big)
big_list_sum = sum(big_list)
small_list_sum = sum(small_list)
if big_list_sum > small_list_sum:
return ( (big_list, small_list))
else:
return (( small_list, big_list))
tests = [ [1,2,3,4,5,6,700,800],
[10001,10000,100,90,50,1],
range(1, 11),
[12312, 12311, 232, 210, 30, 29, 3, 2, 1, 1]]
for l in tests:
l.sort()
print
print “Source List:\t”, l
l1,l2 = mean(l)
print “Result List:\t”, l1, l2
print “Distance:\t”, abs(sum(l1)-sum(l2))
print ‘-*’*40输出结果
Python代码
Source List: [1, 2, 3, 4, 5, 6, 700, 800]
Result List: [1, 4, 5, 800] [2, 3, 6, 700]
Distance: 99
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Source List: [1, 50, 90, 100, 10000, 10001]
Result List: [50, 90, 10000] [1, 100, 10001]
Distance: 38
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Source List: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Result List: [2, 3, 6, 7, 10] [1, 4, 5, 8, 9]
Distance: 1
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Source List: [1, 1, 2, 3, 29, 30, 210, 232, 12311, 12312]
Result List: [1, 3, 29, 232, 12311] [1, 2, 30, 210, 12312]
Distance: 21
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
1 Python的函数参数传递
看两个例子:
a = 1
def fun(a):
a = 2
fun(a)
print a # 1
a = []
def fun(a):
a.append(1)
fun(a)
print a # [1]
所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。
这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。(这就是这个问题的重点)
当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.
如果还不明白的话,这里有更好的解释: http://*.com/questions/986006/how-do-i-pass-a-variable-by-reference14
2 Python中的元类(metaclass)
这个非常的不常用,但是像ORM这种复杂的结构还是会需要的,详情请看:http://*.com/questions/100003/what-is-a-metaclass-in-python
3 @staticmethod和@classmethod
Python其实有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法,如下:
def foo(x):
print "executing foo(%s)"%(x)
class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
@classmethod
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x)
@staticmethod
def static_foo(x):
print "executing static_foo(%s)"%x
a=A()
这里先理解下函数参数里面的self和cls.这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用foo(x),这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是foo(self, x),为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的a.foo(x)(其实是foo(a, x)).类方法一样,只不过它传递的是类而不是实例,A.class_foo(x).注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好.
对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用a.static_foo(x)或者A.static_foo(x)来调用.
|\|实例方法|类方法|静态方法|
|:--|:--|:--|:--|
|a = A()|a.foo(x)|a.class_foo(x)|a.static_foo(x)|
|A|不可用|A.class_foo(x)|A.static_foo(x)|
4 类变量和实例变量
class Person:
name="aaa"
p1=Person()
p2=Person()
p1.name="bbb"
print p1.name # bbb
print p2.name # aaa
print Person.name # aaa
类变量就是供类使用的变量,实例变量就是供实例使用的.
这里p1.name="bbb"是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,p1.name一开始是指向的类变量name="aaa",但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了.
可以看看下面的例子:
class Person:
name=[]
p1=Person()
p2=Person()
p1.name.append(1)
print p1.name # [1]
print p2.name # [1]
print Person.name # [1]
参考:http://*.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block
5 Python自省
这个也是python彪悍的特性.
自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().
6 字典推导式
可能你见过列表推导时,却没有见过字典推导式,在2.7中才加入的:
d = {key: value for (key, value) in iterable}
7 Python中单下划线和双下划线
>>> class MyClass():
... def __init__(self):
... self.__superprivate = "Hello"
... self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}
__foo__:一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突.
_foo:一种约定,用来指定变量私有.程序员用来指定私有变量的一种方式.
__foo:这个有真正的意义:解析器用_classname__foo来代替这个名字,以区别和其他类相同的命名.
详情见:http://*.com/questions/1301346/the-meaning-of-a-single-and-a-double-underscore-before-an-object-name-in-python
或者: http://www.zhihu.com/question/197549413
8 字符串格式化:%和.format
.format在许多方面看起来更便利.对于%最烦人的是它无法同时传递一个变量和元组.你可能会想下面的代码不会有什么问题:
"hi there %s" % name
但是,如果name恰好是(1,2,3),它将会抛出一个TypeError异常.为了保证它总是正确的,你必须这样做:
"hi there %s" % (name,) # 提供一个单元素的数组而不是一个参数
但是有点丑..format就没有这些问题.你给的第二个问题也是这样,.format好看多了.
你为什么不用它?
不知道它(在读这个之前)
为了和Python2.5兼容(譬如logging库建议使用%(issue #4))
Python string formatting: % vs. .format
asked by NorthIsUpon 06:46PM - 22 Feb 11
python, performance, logging, string-formatting
9 迭代器和生成器
最近打算用Python做分词,在生成字典的时候,我采用的方法是逐个元素处理的方法,结果由于训练语料中的数据量过大,这样处理很慢。所以打算学学迭代器与生成器,看看能不能对序列进行批量处理(这点和matlab有点像)以下内容转载自:http://blog.****.net/chszs/archive/2009/01/24/3852669.aspx 把美文自己索罗到博客中来,我的博客就可以成为一个小的资料库了
Python的迭代器和生成器
Iterator是迭代器的意思,它的作用是一次产生一个数据项,直到没有为止。这样在 for 循环中就可以对它进行循环处理了。那么它与一般的序列类型(list, tuple等)有什么区别呢?它一次只返回一个数据项,占用更少的内存。但它需要记住当前的状态,以便返回下一数据项。它是一个有着next()方法的对象。而序列类型则保存了所有的数据项,它们的访问是通过索引进行的。
一、迭代器Iterators
迭代器仅是一容器对象,它实现了迭代器协议。它有两个基本方法:
1)next方法
返回容器的下一个元素
2)__iter__方法
返回迭代器自身
迭代器可使用内建的iter方法创建,见例子:
>>> i = iter('abc')
>>> i.next()
'a'
>>> i.next()
'b'
>>> i.next()
'c'
>>> i.next()
Traceback (most recent call last):
File "<string>", line 1, in <string>
StopIteration:
class MyIterator(object):
def __init__(self, step):
self.step = step
def next(self):
"""Returns the next element."""
if self.step==0:
raise StopIteration
self.step-=1
return self.step
def __iter__(self):
"""Returns the iterator itself."""
return self
for el in MyIterator(4):
print el
--------------------
结果:
3
2
1
0
二、生成器Generators
从Python2.2起,生成器提供了一种简洁的方式帮助返回列表元素的函数来完成简单和有效的代码。
它基于yield指令,允许停止函数并立即返回结果。
此函数保存其执行上下文,如果需要,可立即继续执行。
例如Fibonacci函数:
def fibonacci():
a,b=0,1
while True:
yield b
a,b = b, a+b
fib=fibonacci()
print fib.next()
print fib.next()
print fib.next()
print [fib.next() for i in range(10)]
--------------------
结果:
1
1
2
[3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
PEP Python Enhancement Proposal Python增强建议
tokenize模块
>>> import tokenize
>>> reader = open('c:/temp/py1.py').next
>>> tokens=tokenize.generate_tokens(reader)
>>> tokens.next()
(1, 'class', (1, 0), (1, 5), 'class MyIterator(object):\n')
>>> tokens.next()
(1, 'MyIterator', (1, 6), (1, 16), 'class MyIterator(object):\n')
>>> tokens.next()
(51, '(', (1, 16), (1, 17), 'class MyIterator(object):\n')
例子:
def power(values):
for value in values:
print 'powering %s' %value
yield value
def adder(values):
for value in values:
print 'adding to %s' %value
if value%2==0:
yield value+3
else:
yield value+2
elements = [1,4,7,9,12,19]
res = adder(power(elements))
print res.next()
print res.next()
--------------------
结果:
powering 1
adding to 1
3
powering 4
adding to 4
7
保持代码简单,而不是数据。
注意:宁可有大量简单的可迭代函数,也不要一个复杂的一次只计算出一个值的函数。
例子:
def psychologist():
print 'Please tell me your problems'
while True:
answer = (yield)
if answer is not None:
if answer.endswith('?'):
print ("Don't ask yourself too much questions")
elif 'good' in answer:
print "A that's good, go on"
elif 'bad' in answer:
print "Don't be so negative"
free = psychologist()
print free.next()
print free.send('I feel bad')
print free.send("Why I shouldn't ?")
print free.send("ok then i should find what is good for me")
--------------------
结果:
Please tell me your problems
None
Don't be so negative
None
Don't ask yourself too much questions
None
A that's good, go on
None
10 *args and **kwargs
用*args和**kwargs只是为了方便并没有强制使用它们.
当你不确定你的函数里将要传递多少参数时你可以用*args.例如,它可以传递任意数量的参数:
>>> def print_everything(*args):
for count, thing in enumerate(args):
... print '{0}. {1}'.format(count, thing)
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage
相似的,**kwargs允许你使用没有事先定义的参数名:
>>> def table_things(**kwargs):
... for name, value in kwargs.items():
... print '{0} = {1}'.format(name, value)
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit
你也可以混着用.命名参数首先获得参数值然后所有的其他参数都传递给*args和**kwargs.命名参数在列表的最前端.例如:
def table_things(titlestring, **kwargs)
*args和**kwargs可以同时在函数的定义中,但是*args必须在**kwargs前面.
当调用函数时你也可以用*和**语法.例如:
>>> def print_three_things(a, b, c):
... print 'a = {0}, b = {1}, c = {2}'.format(a,b,c)
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat
就像你看到的一样,它可以传递列表(或者元组)的每一项并把它们解包.注意必须与它们在函数里的参数相吻合.当然,你也可以在函数定义或者函数调用时用*.
asked by MacPythonon 08:28AM - 03 Aug 10
python, args, kwargs
11 面向切面编程AOP和装饰器
这个AOP一听起来有点懵,同学面阿里的时候就被问懵了...
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
12 鸭子类型
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。
比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。
又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,所以它的参数可以是list/tuple/dict/字符串/生成器等.
鸭子类型在动态语言中经常使用,非常灵活,使得python不想java那样专门去弄一大堆的设计模式。
13 Python中重载
函数重载主要是为了解决两个问题。
可变参数类型。
可变参数个数。
另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。
好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。
那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。
好了,鉴于情况 1 跟 情况 2 都有了解决方案,python 自然就不需要函数重载了。
问题可以了解下(新式类是广度优先,旧式类是深度优先),里讲的也很多.
15 __new__和__init__的区别
这个__new__确实很少见到,先做了解吧.
__new__是一个静态方法,而__init__是一个实例方法.
__new__方法会返回一个创建的实例,而__init__什么都不返回.
只有在__new__返回一个cls的实例时后面的__init__才能被调用.
当创建一个新实例时调用__new__,初始化一个实例时用__init__.
ps: __metaclass__是创建类时起作用.所以我们可以分别使用__metaclass__,__new__和__init__来分别在类创建,实例创建和实例初始化的时候做一些小手脚.
16 单例模式
这个绝对常考啊.绝对要记住1~2个方法,当时面试官是让手写的.
1 使用__new__方法
class Singleton(object):
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
class MyClass(Singleton):
a = 1
2 共享属性
创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法.
class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob
class MyClass2(Borg):
a = 1
3 装饰器版本
def singleton(cls, *args, **kw):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls(*args, **kw)
return instances[cls]
return getinstance
@singleton
class MyClass:
...
4 import方法
作为python的模块是天然的单例模式
# mysingleton.py
class My_Singleton(object):
def foo(self):
pass
my_singleton = My_Singleton()
# to use
from mysingleton import my_singleton
my_singleton.foo()
17 Python中的作用域
Python 中,一个变量的作用域总是由在代码中被赋值的地方所决定的。
当 Python 遇到一个变量的话他会按照这样的顺序进行搜索:
本地作用域(Local)→当前作用域被嵌入的本地作用域(Enclosing locals)→全局/模块作用域(Global)→内置作用域(Built-in)
18 GIL线程全局锁
线程全局锁(Global Interpreter Lock),即Python为了保证线程安全而采取的独立线程运行的限制,说白了就是一个核只能在同一时间运行一个线程.
解决办法就是多进程和下面的协程(协程也只是单CPU,但是能减小切换代价提升性能).
19 协程
简单点说协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是用户自己控制切换的时机,不再需要陷入系统的内核态.
Python里最常见的yield就是协程的思想!可以查看第九个问题.
20 闭包
闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。
当一个内嵌函数引用其外部作作用域的变量,我们就会得到一个闭包. 总结一下,创建一个闭包必须满足以下几点:
必须有一个内嵌函数
内嵌函数必须引用外部函数中的变量
外部函数的返回值必须是内嵌函数
感觉闭包还是有难度的,几句话是说不明白的,还是查查相关资料.
重点是函数运行后并不会被撤销,就像16题的instance字典一样,当函数运行完后,instance并不被销毁,而是继续留在内存空间里.这个功能类似类里的类变量,只不过迁移到了函数上.
闭包就像个空心球一样,你知道外面和里面,但你不知道中间是什么样.
21 lambda函数
其实就是一个匿名函数,为什么叫lambda?因为和后面的函数式编程有关.
推荐: 知乎3
22 Python函数式编程
这个需要适当的了解一下吧,毕竟函数式编程在Python中也做了引用.
python中函数式编程支持:
filter 函数的功能相当于过滤器。调用一个布尔函数bool_func来迭代遍历每个seq中的元素;返回一个使bool_seq返回值为true的元素的序列。
>>>a = [1,2,3,4,5,6,7]
>>>b = filter(lambda x: x > 5, a)
>>>print b
>>>[6,7]
map函数是对一个序列的每个项依次执行函数,下面是对一个序列每个项都乘以2:
>>> a = map(lambda x:x*2,[1,2,3])
>>> list(a)
[2, 4, 6]
reduce函数是对一个序列的每个项迭代调用函数,下面是求3的阶乘:
>>> reduce(lambda x,y:x*y,range(1,4))
6
23 Python里的拷贝
引用和copy(),deepcopy()的区别
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝
a.append(5) #修改对象a
a[4].append('c') #修改对象a中的['a', 'b']数组对象
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
输出结果:
a = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
b = [1, 2, 3, 4, ['a', 'b', 'c'], 5]
c = [1, 2, 3, 4, ['a', 'b', 'c']]
d = [1, 2, 3, 4, ['a', 'b']]
24 Python垃圾回收机制
Python GC主要使用引用计数(reference counting)来跟踪和回收垃圾。在引用计数的基础上,通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用问题,通过“分代回收”(generation collection)以空间换时间的方法提高垃圾回收效率。
1 引用计数
PyObject是每个对象必有的内容,其中ob_refcnt就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt就会增加,当引用它的对象被删除,它的ob_refcnt就会减少.引用计数为0时,该对象生命就结束了。
优点:
简单
实时性
缺点:
维护引用计数消耗资源
循环引用
2 标记-清除机制
基本思路是先按需分配,等到没有空闲内存的时候从寄存器和程序栈上的引用出发,遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。
3 分代技术
分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。
Python默认定义了三代对象集合,索引数越大,对象存活时间越长。
举例:
当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。
26 Python的is
is是对比地址,==是对比值
27 read,readline和readlines
read 读取整个文件
readline 读取下一行,使用生成器方法
readlines 读取整个文件到一个迭代器以供我们遍历
解释一下 Django 和 Tornado 的关系、差别
Django源自一个在线新闻 Web站点,于 2005 年以开源的形式被释放出来。
Django 框架的核心组件有:
用于创建模型的对象关系映射为最终用户设计的完美管理界面一流的 URL 设计设计者友好的模板语言缓存系统等等
它鼓励快速开发,并遵循MVC设计。Django遵守 BSD版权,最新发行版本是Django
1.4,于2012年03月23日发布.Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很方便的以“插件”形式服务于整个框架,Django有许多功能强大的第三方插件,你甚至可以很方便的开发出自己的工具包。这使得Django具有很强的可扩展性。它还强调快速开发和DRY(Do Not RepeatYourself)原则。
Tornado是 FriendFeed使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像 web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具和优化。
Tornado 和现在的主流 Web 服务器框架(包括大多数Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对epoll的运用,Tornado 每秒可以处理数以千计的连接,这意味着对于实时 Web服务来说,Tornado 是一个理想的 Web 框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。(关于如何扩容 服务器,以处理数以千计的客户端的连接的问题。
解释下django-debug-toolbar的使用
使用django开发站点时,可以使用django-debug-toolbar来进行调试。在settings.py中添加’debug_toolbar.middleware.DebugToolbarMiddleware’到项目的MIDDLEWARE_CLASSES 内。
解释下Django使用redis缓存服务器
为了能在Django中使用redis,还需要安装redis for Django的插件。然后在Django的settings中配置了。现在连接和配置都已经完成了,接下来是一个简单的例子:
解释下Http协议
HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。
HTTP协议的主要特点可概括如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
解释下Http请求头和常见响应状态码
Accept:指浏览器或其他客户可以接爱的MIME文件格式。可以根据它判断并返回适当的文件格式。
Accept-Charset:指出浏览器可以接受的字符编码。英文浏览器的默认值是ISO-8859-1.
Accept-Language:指出浏览器可以接受的语言种类,如en或en-us,指英语。
Accept-Encoding:指出浏览器可以接受的编码方式。编码方式不同于文件格式,它是为了压缩文件并加速文件传递速度。浏览器在接收到Web响应之后先解码,然后再检查文件格式。
Cache-Control:设置关于请求被代理服务器存储的相关选项。一般用不到。
Connection:用来告诉服务器是否可以维持固定的HTTP连接。HTTP/1.1使用Keep-Alive为默认值,这样,当浏览器需要多个文件时(比如一个HTML文件和相关的图形文件),不需要每次都建立连接。
Content-Type:用来表名request的内容类型。可以用HttpServletRequest的getContentType()方法取得。
Cookie:浏览器用这个属性向服务器发送Cookie。Cookie是在浏览器中寄存的小型数据体,它可以记载和服务器相关的用户信息,也可以用来实现会话功能。
状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:
1xx:指示信息–表示请求已接收,继续处理
2xx:成功–表示请求已被成功接收、理解、接受
3xx:重定向–要完成请求必须进行更进一步的操作
4xx:客户端错误–请求有语法错误或请求无法实现
5xx:服务器端错误–服务器未能实现合法的请求
常见状态代码、状态描述、说明:
200 OK //客户端请求成功
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
eg:HTTP/1.1 200 OK (CRLF)
1.python下多线程的限制以及多进程中传递参数的方式?
python多线程有个全局解释器锁(global interpreter lock),这个锁的意思是任一时间只能有一个线程使用解释器,跟单cpu跑多个程序一个意思,大家都是轮着用的,这叫“并发”,不是“并行”。
多进程间共享数据,可以使用 multiprocessing.Value 和 multiprocessing.Array
试题NO.02
2.Python是如何进行内存管理的?
Python引用了一个内存池(memory pool)机制,即Pymalloc机制(malloc:n.分配内存),用于管理对小块内存的申请和释放
内存池(memory pool)的概念:
当 创建大量消耗小内存的对象时,频繁调用new/malloc会导致大量的内存碎片,致使效率降低。内存池的概念就是预先在内存中申请一定数量的,大小相等 的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后再申请新的内存。这样做最显著的优势就是能够减少内存碎片,提升效率。
内存池的实现方式有很多,性能和适用范围也不一样。
python中的内存管理机制——Pymalloc:
python中的内存管理机制都有两套实现,一套是针对小对象,就是大小小于256bits时,pymalloc会在内存池中申请内存空间;当大于256bits,则会直接执行new/malloc的行为来申请内存空间。 关于释放内存方面,当一个对象的引用计数变为0时,python就会调用它的析构函数。在析构时,也采用了内存池机制,从内存池来的内存会被归还到内存池中,以避免频繁地释放动作。
试题NO.03
3.什么是lambda函数?它有什么好处?
lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数。 lambda 函数不能包含命令,它们所包含的表达式不能超过一个。不要试图向lambda 函数中塞入太多的东西;如果你需要更复杂的东西,应该定义一个普通函数,然后想让它多长就多长。
试题NO.04
4.如何用Python输出一个Fibonacci数列?
1 a,b = 0, 1
2 while b<100:
3 print (b),
4 a, b = b, a+b
试题NO.05
5.介绍一下Python中webbrowser的用法?
webbrowser模块提供了一个高级接口来显示基于Web的文档,大部分情况下只需要简单的调用open()方法。
webbrowser定义了如下的异常:
exception webbrowser.Error, 当浏览器控件发生错误是会抛出这个异常
webbrowser有以下方法:
webbrowser.open(url[, new=0[, autoraise=1]])
这个方法是在默认的浏览器中显示url, 如果new = 0, 那么url会在同一个浏览器窗口下打开,如果new = 1, 会打开一个新的窗口,如果new = 2, 会打开一个新的tab, 如果autoraise = true, 窗口会自动增长。
webbrowser.open_new(url)
在默认浏览器中打开一个新的窗口来显示url, 否则,在仅有的浏览器窗口中打开url
webbrowser.open_new_tab(url)
在默认浏览器中当开一个新的tab来显示url, 否则跟open_new()一样
webbrowser.get([name]) 根据name返回一个浏览器对象,如果name为空,则返回默认的浏览器
webbrowser.register(name, construtor[, instance])
注册一个名字为name的浏览器,如果这个浏览器类型被注册就可以用get()方法来获取。
试题NO.06
6.解释一下python的and-or语法
与C表达式 bool ? a : b类似,但是bool and a or b,当 a 为假时,不会象C表达式 bool ? a : b 一样工作
应该将 and-or 技巧封装成一个函数:
def choose(bool, a, b):
return (bool and [a] or [b])[0]
因为 [a] 是一个非空列表,它永远不会为假。甚至 a 是 0 或 '' 或其它假值,列表[a]为真,因为它有一个元素。
试题NO.07
7.how do I iterate over a sequence in reverse order?
for x in reversed(sequence):
... # do something with x..
如果不是list, 最通用但是稍慢的解决方案是:
for i in range(len(sequence)-1, -1, -1):
x = sequence[i]
<do something with x>
试题NO.08
8.Python是如何进行类型转换的?
试题NO.09
9.Python里面如何实现tuple和list的转换?
试题NO.10
10.请写出一段Python代码实现删除一个list里面的重复元素?
试题NO.11
11.Python如何实现单例模式?其他23种设计模式python如何实现?
试题NO.12
12.Python里面如何拷贝一个对象?
标准库中的copy模块提供了两个方法来实现拷贝.一个方法是copy,它返回和参数包含内容一样的对象.
使用deepcopy方法,对象中的属性也被复制
试题NO.13
13.如何用Python来进行查询和替换一个文本字符串?
可以使用sub()方法来进行查询和替换,sub方法的格式为:sub(replacement, string[, count=0])
replacement是被替换成的文本
string是需要被替换的文本
count是一个可选参数,指最大被替换的数量
14.Python里面search()和match()的区别?
match()函数只检测RE是不是在string的开始位置匹配,search()会扫描整个string查找匹配, 也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none 。
试题NO.15
微软十五道面试题
1、有一个整数数组,请求出两两之差绝对值最小的值,
记住,只要得出最小值即可,不需要求出是哪两个数。
##############一般解法################
def foo(data1,data2):
min=abs(data1[0]-data2[0])
for i in data1:
for j in data2:
if abs(i-j)<min:
min=abs(i-j)
return min
a=[132,43,-1876,565,1]
b=[85,-63443,569,-1899,135]
c=foo(a,b)
print c
#################oneliner#####################
>>> a=[132,43,-1876,565,1]
>>> b=[85,-63443,569,-1899,135]
>>> c=min(abs(i-j) for i in a for j in b)
>>> c
3
这里有一个技巧,[abs(i-j) for i in a for j in b]会生成一个list,使用大量的存储空间,而(abs(i-j) for i in a for j in b)则产生一个生成器。
2、写一个函数,检查字符是否是整数,如果是,返回其整数值。(或者:怎样只用4行代码编写出一个从字符串到长整形的函数?)
用python解这题很方便,内置函数isdigit()和int()可以实现:
a=raw_input('a:')
print type(a)
print a.isdigit()
a=int(a)
print type(a)
结果如下:
a:43627856823958612387568912365
<type'str'>
True
<type'long'>
3、给出一个函数来输出一个字符串的所有排列。
这题一看就是各种迭代吧,自然想到一个python标准库--itertools:
from itertools import permutations
>>> a='nice'
>>> for element in list(itertools.permutations(a, 4)):
print ''.join(element),' ',
nice niec ncie ncei neic neci ince inec icne icen ienc iecn cnie cnei cine cien ceni cein enic enci einc eicn ecni ecin
4、给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠
基本思路:
先判断两个字符串长度,再使用内置函数a.endswith()或b.startswith()寻找重叠部分。
a='abcdefghijklmnop'
b='ijklmnopqrstuvwxyz'
minlen=min(len(a),len(b))
i=0
while i:
if a.endswith(b[:i+1]):
break
else:
i+=1
if i== minlen:
newstr=a+b
else:
newstr=a+b[i+1:]
print newstr
5、怎样编写一个程序,把一个有序整数数组放到二叉树中?
6、怎样从顶部开始逐层打印二叉树结点数据?请编程。
Python的二叉树还没有研究过。。。先放一下。。。
7、怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?
使用内置reverse()函数或者使用a[-1::-1]都可以
8、请编写能直接实现int atoi(const char * pstr)函数功能的代码。
不适用int()函数。考虑两种情况:输入‘1234’,输出1234;输入‘1234.56’,输出‘1234’。
‘1’肿么转换成1?ord('1')-ord('0')
def my_atoi(data):
integer=data.split('.')[0]
result=0
for i,ele in enumerate(integer):
result+=(ord(ele)-ord('0'))*10**(len(integer)-i-1)
return result
a='1234'
b='1234.56'
print my_atoi(a)
print my_atoi(b)
10、在排序数组中,找出给定数字的出现次数
比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。
内置函数count()
11、平面上N个点,每两个点都确定一条直线,
求出斜率最大的那条直线所通过的两个点(斜率不存在的情况不考虑)。时间效率越高越好。
同样使用itertools库,方便的两两组合N个点
from itertools import combinations
A=(1,4)
B=(2,1)
C=(4,3)
D=(5,5)
E=(8,2)
name='ABCDE'
pos=[A,B,C,D,E]
name_com=combinations(name,2)
pos_com=combinations(pos,2)
def cal_rate(data1,data2):
return (data1[1]-data2[1])/(data1[0]-data2[0])
rates=[]
for ele in list(pos_com):
rates.append(cal_rate(ele[0],ele[1]))
print rates
print rates.index(max(rates))
print list(name_com)[rates.index(max(rates))]
运行结果:
[-3, -1, 0, -1, 1, 1, 0, 2, -1, -1]
7
('C', 'D')
12、一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。
请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。
注意:
- 5个数值允许是乱序的。比如: 8 7 5 0 6
- 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4
- 0可以多次出现。
- 复杂度如果是O(n2)则不得分。
我的思路:不管有几个零,非零整数两两之差最大值小于等于4。因此做一次循环,求出数列中的最大值和最小值,两者相减即可。这里需要考虑的细节是求出去零以外的最小值以及数列如果全零的情况。
a=[1,4,5,2,3]
b=[0,0,0,0,0]
c=[6,1,0,2,5]
d=[4,0,7,8,0]
def foo(data):
maxint=max(data)
minint=maxint
if minint==0:
return True
else:
for i in data:
if i<minint:
minint=i
if maxint-minint<=4:
return True
else:
return False
print foo(a) #True
print foo(b) #True
print foo(c) #False
print foo(d) #False
其实这里还有一个问题,如何产生随机数列,且零能重复,其他数字不能重复。
from random import randint
array=[]
while len(array)<=5:
x=randint(0,65535)
if x==0 or x not in array:
array.append(x)
python 面试题总结
浪漫杀手 2012-10-13 11:27:37
Python面试题:请写出一段Python代码实现删除一个list里面的重复元素:
一、自己的思路:
遍历列表,发现元素不同,添加到新列表C中。
最后将C列表赋值给原列表
def select(a):
i=None
c=[]
for b in a:
if i!=b:
c.append(b)
i=b
a[0:]=c
自我总结:
1.
迭代器的迭代方式(按索引迭代)
for b in c:
print str(b)
这种迭代方式是按索引来的。
如果在迭代过程中对原列表进行操作,会产生奇怪的记过。
例子:
>>> c=[1,2,3,4]
>>> for b in c:
print "before:"+str(b)
c.remove(b)
print "after:"+str(b)
before:1
after:1
before:3
after:3
从这个例子能学到:如果在迭代时删除某个元素,会导致列表改变,但是迭代器依旧以原来的索引顺序迭代,这会导致数据错位,引起bug
2.编写循环逻辑注意点:
一般只是简单的for循环是比较简单的,但是如果伴随着相应变量的变更,变量的读取,就会比较容易出错。
2.1怎么减小错误呢?.最简单的方法,画图,一个循环一个图,就比较容易想清楚了。
2.2怎么提高编程能力?特别面对循环时?
首先,是积累,脑子里需要建立一个知识库。(类似的问题该怎么解决)
其次,是在编程时,用到积累的知识需要和环境结合,可能思维会乱,可以画图
最后,就是归纳第二步的思维,这样就能写出程序了
3.参数传递,与值的改变
如果a引用了一个对象,那么将a传入select函数。在select改变行参的值不影响外界a的值。
只有改变a所指向内存的值,才能改变a的值
4.当对数据进行操作时,需要考虑此操作是否会影响以后的操作。
二:网上比较好的答案:
思路:从后往前,遍历,这样删除元素此也不会影响以后遍历时取值的操作
代码:
def sort_select(a):
if not a: print 'there is nothing in a'
else:
temp = a[-1]
for i in range(len(a)-2,-1,-1):
if a[i]==temp:del a[i]
else:temp=a[i]
总结:
range函数的起始于结束:
for i in range(100):
print str(i)
输出结果:打印从1到99
for i in range(5,-1,-1):
print str(i)
输出结果:打印从5到0
碰到这种问题的经验:
1.要用循环
2.因为是对列表删除操作,又要遍历整个列表,所以从后往前遍历比较好,就算删除了后面的元素,也不会影响前面元素的顺序
3.首先一个中间值(temp),temp等于该列表的最后一个值。
将temp与从后往前遍历来的值对比
如果 相等,就删除
否则 就 将值赋给temp,一边下次循环比较
简述__new__和__init__的区别
创建一个新实例时调用__new__,初始化一个实例时用__init__,这是它们最本质的区别。
new方法会返回所构造的对象,init则不会.
new函数必须以cls作为第一个参数,而init则以self作为其第一个参数
如何捕获异常,常用的异常机制有哪些?
如果我们没有对异常进行任何预防,那么在程序执行的过程中发生异常,就会中断程序,调用python默认的异常处理器,并在终端输出异常信息。
try…except…finally语句:当try语句执行时发生异常,回到try语句层,寻找后面是否有except语句。找到except语句后,会调用这个自定义的异常处理器。except将异常处理完毕后,程序继续往下执行。finally语句表示,无论异常发生与否,finally中的语句都要执行。
assert语句:判断assert后面紧跟的语句是True还是False,如果是True则继续执行print,如果是False则中断程序,调用默认的异常处理器,同时输出assert语句逗号后面的提示信息。
with语句:如果with语句或语句块中发生异常,会调用默认的异常处理器处理,但文件还是会正常关闭。
1 b 2b 3.b4a5c6a7c
高德软件有限公司python试题 及 答案
本文地址: http://blog.****.net/caroline_wendy/article/details/25230835
by Spike 2014.5.7
本题目仅供学术交流, 严禁用于其他目的, 答案仅供参考.
1. 在Python中, list, tuple, dict, set有什么区别, 主要应用在什么样的场景?
解答:
定义:
list: 链表, 有序的项目, 通过索引进行查找, 使用方括号"[]";
tuple: 元组, 元组将多样的对象集合到一起, 不能修改, 通过索引进行查找, 使用括号"()";
dict: 字典, 字典是一组键(key)和值(value)的组合, 通过键(key)进行查找, 没有顺序, 使用大括号"{}";
set: 集合,无序, 元素只出现一次, 自动去重, 使用"set([])";
应用场景:
list, 简单的数据集合, 可以使用索引;
tuple, 把一些数据当做一个整体去使用, 不能修改;
dict, 使用键值和值进行关联的数据;
set, 数据只出现一次, 只关心数据是否出现, 不关心其位置;
代码:
[python] view plain copy print?
mylist = [1, 2, 3, 4, 'Oh']
mytuple = (1, 2, 'Hello', (4, 5))
mydict = {'Wang' : 1, 'Hu' : 2, 'Liu' : 4}
myset = set(['Wang', 'Hu', 'Liu', 4, 'Wang'])
mylist = [1, 2, 3, 4, 'Oh']
mytuple = (1, 2, 'Hello', (4, 5))
mydict = {'Wang' : 1, 'Hu' : 2, 'Liu' : 4}
myset = set(['Wang', 'Hu', 'Liu', 4, 'Wang'])
2. 静态函数, 类函数, 成员函数的区别?
解答:
定义:
静态函数(@staticmethod): 即静态方法,主要处理与这个类的逻辑关联;
类函数(@classmethod): 即类方法, 更关注于从类中调用方法, 而不是在实例中调用方法, 可以用作方法重载, 传入参数cls;
成员函数: 实例的方法, 只能通过实例进行调用;
具体应用:
日期的方法, 可以通过实例化(__init__)进行数据输出, 传入参数self;
可以通过类的方法(@classmethod)进行数据转换, 传入参数cls;
可以通过静态方法(@staticmethod)进行数据验证;
代码:
[python] view plain copy print?
# -*- coding: utf-8 -*-
#eclipse pydev, python 3.3
#by C.L.Wang
class Date(object):
day = 0
month = 0
year = 0
def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year
def display(self):
return "{0}*{1}*{2}".format(self.day, self.month, self.year)
@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1
@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999
date1 = Date('12', '11', '2014')
date2 = Date.from_string('11-13-2014')
print(date1.display())
print(date2.display())
print(date2.is_date_valid('11-13-2014'))
print(Date.is_date_valid('11-13-2014'))
# -*- coding: utf-8 -*-
#eclipse pydev, python 3.3
#by C.L.Wang
class Date(object):
day = 0
month = 0
year = 0
def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year
def display(self):
return "{0}*{1}*{2}".format(self.day, self.month, self.year)
@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1
@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999
date1 = Date('12', '11', '2014')
date2 = Date.from_string('11-13-2014')
print(date1.display())
print(date2.display())
print(date2.is_date_valid('11-13-2014'))
print(Date.is_date_valid('11-13-2014'))
3. a=1, b=2, 不用中间变量交换a和b的值
解答:
两种形式: 加法或异或
代码:
[python] view plain copy print?
a = 1
b = 2
a = a + b
b = a - b
a = a - b
print ('a = {0}, b = {1}'.format(a, b))
a = a ^ b
b = a ^ b
a = a ^ b
print ('a = {0}, b = {1}'.format(a, b))
a = 1
b = 2
a = a + b
b = a - b
a = a - b
print ('a = {0}, b = {1}'.format(a, b))
a = a ^ b
b = a ^ b
a = a ^ b
print ('a = {0}, b = {1}'.format(a, b))
4. 写一个函数, 输入一个字符串, 返回倒序排列的结果: 如: string_reverse(‘abcdef’), 返回: ‘fedcba’
(请采用多种方法实现, 并对实现方法进行比较)
解答:
5种方法的比较:
1. 简单的步长为-1, 即字符串的翻转;
2. 交换前后字母的位置;
3. 递归的方式, 每次输出一个字符;
4. 双端队列, 使用extendleft()函数;
5. 使用for循环, 从左至右输出;
代码:
[python] view plain copy print?
string = 'abcdef'
def string_reverse1(string):
return string[::-1]
def string_reverse2(string):
t = list(string)
l = len(t)
for i,j in zip(range(l-1, 0, -1), range(l//2)):
t[i], t[j] = t[j], t[i]
return "".join(t)
def string_reverse3(string):
if len(string) <= 1:
return string
return string_reverse3(string[1:]) + string[0]
from collections import deque
def string_reverse4(string):
d = deque()
d.extendleft(string)
return ''.join(d)
def string_reverse5(string):
#return ''.join(string[len(string) - i] for i in range(1, len(string)+1))
return ''.join(string[i] for i in range(len(string)-1, -1, -1))
print(string_reverse1(string))
print(string_reverse2(string))
print(string_reverse3(string))
print(string_reverse4(string))
print(string_reverse5(string))
string = 'abcdef'
def string_reverse1(string):
return string[::-1]
def string_reverse2(string):
t = list(string)
l = len(t)
for i,j in zip(range(l-1, 0, -1), range(l//2)):
t[i], t[j] = t[j], t[i]
return "".join(t)
def string_reverse3(string):
if len(string) <= 1:
return string
return string_reverse3(string[1:]) + string[0]
from collections import deque
def string_reverse4(string):
d = deque()
d.extendleft(string)
return ''.join(d)
def string_reverse5(string):
#return ''.join(string[len(string) - i] for i in range(1, len(string)+1))
return ''.join(string[i] for i in range(len(string)-1, -1, -1))
print(string_reverse1(string))
print(string_reverse2(string))
print(string_reverse3(string))
print(string_reverse4(string))
print(string_reverse5(string))
5. 请用自己的算法, 按升序合并如下两个list, 并去除重复的元素:
list1 = [2, 3, 8, 4, 9, 5, 6]
list2 = [5, 6, 10, 17, 11, 2]
解答:
合并链表, 递归的快速排序, 去重链接;
代码:
[python] view plain copy print?
import random
list1 = [2, 3, 8, 4, 9, 5, 6]
list2 = [5, 6, 10, 17, 11, 2]
def qsort(L):
if len(L)<2: return L
pivot_element = random.choice(L)
small = [i for i in L if i< pivot_element]
large = [i for i in L if i> pivot_element]
return qsort(small) + [pivot_element] + qsort(large)
def merge(list1, list2):
return qsort(list1 + list2)
print(merge(list1, list2))
import random
list1 = [2, 3, 8, 4, 9, 5, 6]
list2 = [5, 6, 10, 17, 11, 2]
def qsort(L):
if len(L)<2: return L
pivot_element = random.choice(L)
small = [i for i in L if i< pivot_element]
large = [i for i in L if i> pivot_element]
return qsort(small) + [pivot_element] + qsort(large)
def merge(list1, list2):
return qsort(list1 + list2)
print(merge(list1, list2))
注: 如果使用set方法, list(set(list1 + list2)), 即可.
6. 请写出打印结果
x = [0, 1]
i = 0
i, x[i] = 1, 2
print(x)
打印结果: [0, 2], python可以使用连续赋值, 从左至右.
g = lambda x, y=2, z : x + y**z
g(1, z=10) = ?
打印结果: 异常, 形参表末尾才可以有默认参数, z需要提供默认参数.
7. 说一下以下代码片段存在的问题
[python] view plain copy print?
from amodule import * # amodule is an exist module
class dummyclass(object):
def __init__(self):
self.is_d = True
pass
class childdummyclass(dummyclass):
def __init__(self, isman):
self.isman = isman
@classmethod
def can_speak(self): return True
@property
def man(self): return self.isman
if __name__ == "__main__":
object = new childdummyclass(True)
print object.can_speak()
print object.man()
print object.is_d
from amodule import * # amodule is an exist module
class dummyclass(object):
def __init__(self):
self.is_d = True
pass
class childdummyclass(dummyclass):
def __init__(self, isman):
self.isman = isman
@classmethod
def can_speak(self): return True
@property
def man(self): return self.isman
if __name__ == "__main__":
object = new childdummyclass(True)
print object.can_speak()
print object.man()
print object.is_d
解答:
1. 警告: object是python新形式(new style)的一个基础类, 不应该被重新定义;
2. 警告: 类方法(classmethod)是类所拥有的方法, 传入的参数应该是cls, 而不是self;
3. 错误: Python没有new关键字, 如需修改new, 如单例模式, 可以重写(override)__new__;
4. 错误: @property, 表示属性, 不是方法, 则不需要加括号”()”, 直接调用object.man, 即可;
5. 错误: 如果想使用基类的成员, 则需要初始化基类, 如dummyclass.__init__(self), 即可;
6. 额外: 类名尽量使用大写.
代码:
[python] view plain copy print?
class dummyclass(object):
def __init__(self):
self.is_d = True
pass
class childdummyclass(dummyclass):
def __init__(self, isman):
dummyclass.__init__(self) #__init__
self.isman = isman
@classmethod
def can_speak(cls): return True #cls
@property
def man(self): return self.isman
if __name__ == "__main__":
o = childdummyclass(True) #new, object
print o.can_speak()
print o.man #property
print o.is_d
class dummyclass(object):
def __init__(self):
self.is_d = True
pass
class childdummyclass(dummyclass):
def __init__(self, isman):
dummyclass.__init__(self) #__init__
self.isman = isman
@classmethod
def can_speak(cls): return True #cls
@property
def man(self): return self.isman
if __name__ == "__main__":
o = childdummyclass(True) #new, object
print o.can_speak()
print o.man #property
print o.is_d
8. 介绍一下python的异常处理机制和自己开发过程中的体会
解答:
Python的异常处理机制:
try: 尝试抛出异常;
raise: 引发异常;
except: 处理异常;
finally: 是否发生异常都需要做的事情;
创建新的异常类型, 需要继承Exception类, 可以定义类的属性, 便于处理异常;
开发体会:
异常主要处理读取文件, 也可以使用with的方法读取文件; 还可以用于网络连接, 异常可以包含大量的错误信息, 进行错误处理.
代码:
[python] view plain copy print?
class ShortInputException(Exception):
def __init__(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
while True:
try:
text = raw_input('Enter somthing-->')
if len(text) < 3:
raise ShortInputException(len(text), 3)
except EOFError:
print('Why did you do an EOF on me')
except ShortInputException as ex:
print('ShortInputException The input was {0} long, \
excepted at least {1}. '.format(ex.length, ex.atleast))
else:
print('No exception was raised. ')
finally:
print('Over')
class ShortInputException(Exception):
def __init__(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
while True:
try:
text = raw_input('Enter somthing-->')
if len(text) < 3:
raise ShortInputException(len(text), 3)
except EOFError:
print('Why did you do an EOF on me')
except ShortInputException as ex:
print('ShortInputException The input was {0} long, \
excepted at least {1}. '.format(ex.length, ex.atleast))
else:
print('No exception was raised. ')
finally:
print('Over')
# -*- coding: gbk -*-
def print_prime_factors(num):
if num < 2:
print '请输入大于 1 的整数用于质因数分解'
return
print '输出:',
prime_num = 2
while prime_num <= num:
if prime_num == num:
print prime_num,
break
elif num % prime_num == 0:
print prime_num,
num /= prime_num
else:
prime_num += 1
if __name__ == '__main__':
num = int(raw_input('输入:'))
print_prime_factors(num)
第一题: give you two var a and b, print the value of a+b, just do it!
根据提议,给出两个变量 a 和 b 并打印出 a+b的值.
1 2 |
a, b = 1, 2 print a + b |
当然也可以这么做
1 2 3 |
a = 1 b = 2 print a + b |
第二题: 给你一个list, 如 L = [2, 8, 3, 5], 对L进行升序排序并输出。
1 2 3 4 5 6 |
L = sorted(L) print L #或 # sort() 内置函数会对列表自身排序而 sorted() 会生成一个新的排序列表 L.sort() print L |
第三题: 给你一个字符串a, 如a = ‘12345', 对a进行逆序输出。
1 2 3 |
# 通过步进来逆序输出字符串。 a = a[::-1] print a |
第四题: 给你一个字典a = {1:1, 2:2, 3:3}, 输出字典a的key ,以',' 连接,如 ‘1,2,3'。
1 2 |
# dict.keys() 会以list返回字典的key.而join会把list按,字符串',' 连接起来。 print ','.join(a.keys()) |
第五题: 给你一个字符串a, 输出字符串奇数位置的字符串,如 a = ‘12345', 则输出 ‘135'
1 2 |
# 通过列表解析(也称列表推导式)来判断下表选取奇偶数。 print ''.join([a[x] for x in range(len(a)) if x % 2 == 0]) |
第六题: 输出所有100以内的素数, 素数之间以空格区分。
1 2 3 4 5 |
# 在加一行print 才能运行通过 L = [x for x in range(2, 101) if not [y for y in range(2, x) if x%y == 0]] for i in L: print L, |
第七题: 已知矩形长a, 宽b, 输出其面积和周长,以一个空格隔开
1 |
print a * b, 2 * (a+b) |
第八题: 给你一个list, 如 L = [0, 1, 2, 3, 4] 输出L的中位数
1 2 3 |
# 中位数是指 对已排序的数集取其中间数,数集为偶数 取中间两数的平均 print sorted(L)[len(L)/2] if len(L) % 2 != 0 else \ (sorted(L)[Len(L)/2] + sorted(L)[len(L)/2 -1 ])/2.0 |
第九题: 给你两个正整数a和b, 输出它们的最大公约数。
1 |
print max([x for x in range(1, a+1) if x in [y for y in range(1, b+1) if b%y == 0]]) |
第十题: 给你两个正整数a和b, 输出它们的最小公倍数.
1 |
print min([x for x in range(a, a*b+1) if x%a==0 and x%b==0]) |
附加题: 利用map/reduce 函数实现数的阶乘 如 5!+4!+3!+2!+1!.
1 2 3 4 |
print map(lambda x: reduce(lambda y,z: y*z, range(1, x+1)), range(1,6)) # print [1, 2, 6, 24, 120], 所以在用reduce合起来 print reduce(lambda a, b: a+b, map(lambda x: \ reduce(lambda y, z: y*z, range(1, x+1)),range(1,6))) |
附加题: 使用filter函数 实现素数
1 |
print filter(lambda x: not [x%i for i in range(2,x) if x%i==0], range(2, 101)) |
- # -*- coding: utf-8 -*-
- def bubbleSort(Data):
- '''''冒泡排序: 时间复杂度最好O(n),平均O(n*n),最坏O(n*n),辅助空间 O(1),算法稳定
- n个数,每次从第一个数开始和相邻的数比较,将大的冒泡到后面去。第一趟将最大的冒泡到最后,
- 然后第二次只需比较0~n-1,将其中最大的冒泡到n-1,依次下去...总共进行n-1趟排序即可
- '''
- if Data:
- for i in range(len(Data)):
- 10. for j in range(len(Data)-i-1):
- 11. if Data[j]>Data[j+1]:
- 12. Data[j],Data[j+1]=Data[j+1],Data[j]
- 13. return Data
- 14.
15. def quickSort(Data,low,high):
- 16. '''''快速排序:O(n*logn),O(n*logn),O(n*n),O(n*logn),不稳定
- 17. 冒泡的改进,被认为是当前最优秀的内部排序算法(当然这也不是绝对的,还要看具体情况)。实现基于分治法:分解-解决-合并。
- 18. 基本思想:
- 19. 1.从数列中取出一个基数,
- 20. 2.将数列中比他大的放在右边,小的在左边。
- 21. 3.两边区间重复2,直到各区间只有一个数。
- 22. 整个算法中的基数就是个坑,跳来跳去,总之比他小始终放一边,大的放另一边就行
- 23. 参考:http://blog.****.net/morewindows/article/details/6684558
- 24. '''
- 25. if low < high:
- 26. left,right,base=low,high,Data[low]
- 27. while left <right:
- 28. #从后往前找比base小的数
- 29. while left <right and Data[right] >=base:
- 30. right-=1
- 31. if left < right:
- 32. Data[left]=Data[right]
- 33. #left+=1 这里直接+1更快,因为Data[left]必然小于base,下次循环不用算
- 34. #从前往后找比base大的数
- 35. while left <right and Data[left] < base:
- 36. left+=1
- 37. if left <right:
- 38. Data[right]=Data[left]
- 39. #right-=1
- 40. #left=right时一趟循环终止,base填回坑里去
- 41. Data[left]=base
- 42. quickSort(Data,low,left-1) #递归左边
- 43. quickSort(Data,left+1,high) #递归右边
- 44.
45. def insertSort(Data):
- 46. '''''插入排序: 时间复杂度最好O(n),平均O(n*n),最坏O(n*n),辅助空间 O(1),算法稳定
- 47. 如果Data不为空则开始比较。Data[0]~Data[j]是排好的序列L1,key是未排待插入数据
- 48. 如果key小于L1的最大值则将进行插入操作,while循环找到比key小的index并将key插入
- 49. 在index后面。while循环用来寻找插入位置并将比key大的数后移,如果key本身比L1的
- 50. 最大值还大则无需插入,直接for循环比较下一个
- 51. '''
- 52. if Data:
- 53. for i in range(1,len(Data)):
- 54. key,j = Data[i],i-1
- 55. while j>=0 and Data[j] > key:
- 56. Data[j+1]=Data[j]
- 57. j-=1
- 58. Data[j+1]=key
- 59. return Data
- 60.
61. def selectSort(Data):
- 62. '''''选择排序: 时间复杂度最好O(n*n),平均O(n*n),最坏O(n*n),辅助空间 O(1),算法不稳定
- 63. n个数,每一趟从待排序列L2中选择最大(或最小)数顺序放在已排好序列L1后面(或前面)
- 64. 总共经过n-1趟可排好,与插入排序相比,都是将数据分为已排和未排序列并将未排元素整理
- 65. 到已排序列中,不同的是插入排序在未排序列中按序整理,选排则是按大小选择整理。
- 66. '''
- 67. if Data:
- 68. for i in range(len(Data)-1):
- 69. minnum=i
- 70. for j in range(i+1,len(Data)):#在L2中寻找最小值
- 71. if Data[j]<Data[minnum]:
- 72. minnum=j
- 73. if minnum != i:#如果找到直接交换,插入在L1后面
- 74. Data[i],Data[minnum]=Data[minnum],Data[i]
- 75. return Data
- 76.
77. def shellSort(Data):
- 78. '''''希尔排序: 时间复杂度最好未知,平均O(pow(n,1.25),最坏未知,辅助空间 O(1),不稳定
- 79. 插入排序的改进,将数据分组,每组m个(m叫步长)每次对每组的第i个元素排序,
- 80. 然后再分组,再排序,直到步长为1.至于分组的方法需要理论推导,此处每次步长都取n/2减半
- 81. 更好的步长选择方法见wiki:http://zh.wikipedia.org/wiki/希尔排序
- 82. 其他实现方法:http://blog.****.net/morewindows/article/details/6668714
- 83. '''
- 84. n=len(Data)
- 85. if n > 1:
- 86. gap=n/2
- 87. while gap > 0:
- 88. for i in range(gap):#按步长插入排序
- 89. for j in range(i+gap,n,gap):
- 90. if Data[j] < Data[j-gap]:
- 91. key = Data[j]
- 92. k=j-gap
- 93. while k >=0 and Data[k] > key:
- 94. Data[k+gap]=Data[k]
- 95. k-=gap
- 96. Data[k+gap]=key
- 97. gap/=2
- 98. return Data
- 99.
- if __name__ =="__main__":
- Data=[3,5,1,56,3,7,34,21,8]
- print Data
- #insertSort(Data)
- #bubbleSort(Data)
- #selectSort(Data)
- #shellSort(Data)
- quickSort(Data,0,len(Data)-1)
- print Data
一、填空题(每空1分,共24分)
1.Python使用符号 三引号 # 标示注释;还有一种叫做’’’’’’的特别注释。
2.表达式 1/4+2.75 的值是 2.75 ;
3、请给出计算231 −1的Python表达式 2**31-1 :
4、给出range(1,10,3)的值 (1,4,7)[1,4,7] :
5、Python的数据类型分为整型 、 字符串型 、 浮点型
、复数等类型。
6、Python序列类型包括 元组 、 序列 、字典 三种;
字典 是Python中唯一的映射类型。
7、Python的除法运算符是 / ,取余运算符是 % 。
8、设s=‘abcdefg’,则s[3]值是‘d’ ,s[3:5]值是 def ‘de’ ,s[:5]值是 abcdef’abcde’s[3:]值是 ‘defg’ ,s[::-1]值是 g 。’gfedcba’
9、删除字典中的所有元素的函数是 def.dictclear()返回列表的函数是 key(),返回包含字典中所有值的列表的函数是 values()判断键在字典中是否存在的函数是 has.dict(key) get()。
二、选择题(每题3分,共36分)
1.下列哪个语句在Python中是非法的? (C )B
A、x = y = z = 1 B、x = (y = z + 1)
C、x, y = y, x D、x += y
2.关于Python内存管理,下列说法错误的是 (B )
A、变量不必事先声明 B、变量无须先创建和赋值而直接使用
C、变量无须指定类型 D、可以使用del释放资源
3、(1) 执行下列语句后的显示结果是什么? ( A)
>>> world=”world”
>>> print “hello”+ world
A、 helloworld B、 “hello”world
C、hello world D、 语法错误
4、下面哪个不是Python合法的标识符 B( )
A、int32 B、40XL C、self D、__name__
5、下列哪种说法是错误的 A( )
A、除字典类型外,所有标准对象均可以用于布尔测试
B、空字符串的布尔值是False
C、空列表对象的布尔值是False
D、值为0的任何数字对象的布尔值是False
6、下列表达式的值为True的是 ( C )
A、5+4j > 2-3j B、3>2>2
C、(3,2)< (‘a’,’b’) D、’abc’ > ‘xyz’
7、Python不支持的数据类型有 A( )
A、char B、int C、float D、list
8、type(1+2L*3.14)的结果是: ( C )
[A] <type ‘int’>
[B] <type ‘long’>
[C] <type ‘float’>
[D] <type ‘str’>
9、关于字符串下列说法错误的是 (B )
A、字符应该视为长度为1的字符串
B、字符串以\0标志字符串的结束
C、既可以用单引号,也可以用双引号创建字符串
D、在三引号字符串中可以包含换行回车等特殊字符
10、以下不能创建一个字典的语句是 ( C )
A、dict1 = {} B、dict2 = { 3 : 5 }
C、dict3 = dict( [2 , 5] ,[ 3 , 4 ] )
D、dict4 = dict( ( [1,2],[3,4] ) )
11、下面不能创建一个集合的语句是 ( C)
A、s1 = set () B、s2 = set (“abcd”)
C、s3 = (1, 2, 3, 4) D、s4 = frozenset( (3,2,1) )
12、下列Python语句正确的是 D( )
A、min = x if x < y else y B、max = x > y ? x : y
C、if (x > y) print x D、while True : pass
三、简答题(每题8分,共40分)
1、编写一个python程序,输入两个数,比较它们的大小并输出其中较大者。
X=input(“输入第一个数:”)
Y=input(“输入第二个数:”)
If(x==y):
Print “两数相同”
Elif(x>y):
Print “较大数为x”
Else:
print“较大数为y”
2、给定一个整数N,判断N是否为素数
3、存在字符串“I,love,python”,取出love,并输出
S=”I,love,python”
A=S[2:6]
print A
4、用Python定义一个函数,输入一年份,判断该年份是否是闰年并输出结果请输入一个年份
Year=int(input(“请输入年份:”))
if((year%4==0&&year%100!=0)||year%400==0)
if year%4==0 and year%100!=0 or year%100==0 :
print“是闰年“
else
print “不是闰年“
5、存在字符串“ab2b3n5n2n67mm4n2”,编程统计字符串中字母n出现的次数
S= “ab2b3n5n2n67mm4n2”
Count=0
For i in s[]
If s[i]==n
Count+=1
Print count
一. 选择题: 将唯一正确的选项写在题前括号中(每题1分,共15分)
【 】1.表达式 '%d%%%d' %(3 / 4, 3 % 4)的值是:
A.'0%3' B.'0%%3' C.'3/4%3%4' D.'3/4%%3%4'
【 】2.下面标识符中不是python语言的保留字的是:
A.continue B.except C.init D.pass
【 】3.以下程序的输出结果是(提示:ord(' a ')==97):
lista = [1,2,3,4,5,'a','b','c','d','e']
print lista[2] + lista[5]
A.100 B.'d' C.d D.TypeEror
【 】4.下面的循环体执行的次数与其它不同的是:
A. i = 0
while( i <= 100):
print i,
i = i + 1
B. for i in range(100):
print i,
C. for i in range(100, 0, -1):
print i,
D. i = 100
while(i > 0):
print i,
i = i – 1
【 】5.自顶向下逐步求精的程序设计方法是指:
A.将一个大问题简化为同样形式的较小问题。
B.先设计类,再实例化为对象。
C.解决方案用若干个较小问题来表达,直至小问题很容易求解。
D.先设计简单版本,再逐步增加功能。
【 】6.简单变量作为实参时,它和对应的形参之间数据传递方式是:
A.由形参传给实参 B.由实参传给形参
C.由实参传给形参,再由形参传给实参 D.由用户指定传递方向
【 】7.以下说法不正确的是:
A.在不同函数中可以使用相同名字的变量。
B.函数可以减少代码的重复,也使得程序可以更加模块化。
C.主调函数内的局部变量,在被调函数内不赋值也可以直接读取。
D.函数体中如果没有return语句,也会返回一个None值。
【 】8.关于list和string下列说法错误的是:
A.list可以存放任意类型。
B.list是一个有序集合,没有固定大小。
C.用于统计string中字符串长度的函数是string.len()。
D.string具有不可变性,其创建后值不能改变。
【 】9.下面问题属于计算机本质上不可解问题的是:
A.Hanoi塔问题 B.排序问题 C.求阶乘 D.Halting问题
【 】10.python语言定义的class的初始化函数的函数名是:
A.init B.__init__ C.__init D.init__
【 】11.已知x = 43,y = False;则表达式(x >= y and 'A' < 'B' and not y)的值是:
A.False B.语法错 C.True D."假"
【 】12.对n个数做归并排序(merge sort),这个算法是:
A.nlogn时间的 B.线性时间的 C.logn时间的 D.n2时间的
【 】13.下面不是计算思维的特征的是:
A.概念化 B.数学与工程思维的融合 C.面向所有的人 D.计算机的思维
【 】14.执行下面操作后,list2的值是:
list1 = [4,5,6]
list2 = list1
list1[2] = 3
A.[4,5,6] B.[4,3,6] C.[4,5,3] D.A,B,C都不正确
【 】15.下列合法的变量名是:
A.main( ) B.car2 C.2car D.var-name
二.概念填空(每空1分,共10分)
1.表达式eval("4 * 2 + 5 % 2 + 4/3")的结果是 。
2.print 'This float, %-10.5f, has width 10 and precision 5. ' % (3.1415926) 的输出结果是:
3.计算的本质是 和 。
4.执行 print 1.3 - 1 == 0.3,结果是False的原因是 。
5.下面语句的执行结果是 。
s = "bb c"
print string.split(3 * s)
6. 、 、 是科技创新的三大支柱。
7.无穷循环while True:的循环体中可用 语句退出循环。
三.阅读程序并回答问题(每题5分,共40分)
1.当输入是54321时,写出下面程序的执行结果。
def main():
num = input(“请输入一个整数:”)
while num != 0:
print num % 10
num = num / 10
main()
答案: 5 4 3 2 1 |
2.写出下面程序的执行结果。
a = [1, 20, 32, 14, 5, 62, 78, 38, 9, 10]
for i in range(9):
if( a[i] > a[i+1] ):
a[i], a[i+1] = a[i+1], a[i]
print a
3.写出下面程序的执行结果。
def main():
lst = [2, 4, 6, 8, 10]
lst = 2 * lst
lst[1], lst[3] = lst[3], lst[1]
swap(lst, 2, 4)
for i in range(len(lst) - 4):
print lst[i], " "
def swap(lists, ind1, ind2):
lists[ind1], lists[ind2] = lists[ind2], lists[ind1]
main()
4.写出下面程序的执行结果。
import string
def main():
s = "I like python!"
s = string.lower(s)
alist = []
countlist = []
count=0
for i in range( len(s) ):
if (ord(s[i]) <= ord('Z') and ord(s[i]) >= ord('A')) \
or (ord(s[i]) <= ord('z') and ord(s[i]) >= ord('a')):
if (s[i] in alist):
sign = alist.index(s[i])
countlist[sign] += 1
else:
alist.append(s[i])
countlist.append(1)
count += 1
for i in range(count):
print alist[i], " ", countlist[i]
main()
1.list 方法
一、创建一个列表
只要把逗号分隔的不同的数据项使用方括号括起来即可。如下所示:
复制代码代码如下:
list1 = ['physics', 'chemistry', 1997, 2000];
list2 = [1, 2, 3, 4, 5 ];
list3 = ["a", "b", "c", "d"];
与字符串的索引一样,列表索引从0开始。列表可以进行截取、组合等。
二、访问列表中的值
使用下标索引来访问列表中的值,同样你也可以使用方括号的形式截取字符,如下所示:
复制代码代码如下:
#!/usr/bin/python
list1 = ['physics', 'chemistry', 1997, 2000];
list2 = [1, 2, 3, 4, 5, 6, 7 ];
print "list1[0]: ", list1[0]
print "list2[1:5]: ", list2[1:5]
以上实例输出结果:
复制代码代码如下:
list1[0]: physics
list2[1:5]: [2, 3, 4, 5]
三、更新列表
你可以对列表的数据项进行修改或更新,你也可以使用append()方法来添加列表项,如下所示:
复制代码代码如下:
#!/usr/bin/python
list = ['physics', 'chemistry', 1997, 2000];
print "Value available at index 2 : "
print list[2];
list[2] = 2001;
print "New value available at index 2 : "
print list[2];
以上实例输出结果:
复制代码代码如下:
Value available at index 2 :
1997
New value available at index 2 :
2001
四、删除列表元素
可以使用 del 语句来删除列表的的元素,如下实例:
复制代码代码如下:
#!/usr/bin/python
list1 = ['physics', 'chemistry', 1997, 2000];
print list1;
del list1[2];
print "After deleting value at index 2 : "
print list1;
以上实例输出结果:
复制代码代码如下:
['physics', 'chemistry', 1997, 2000]
After deleting value at index 2 :
['physics', 'chemistry', 2000]
五、Python列表脚本操作符
列表对 + 和 * 的操作符与字符串相似。+ 号用于组合列表,* 号用于重复列表。
如下所示:
Python 表达式 |
结果 |
描述 |
len([1, 2, 3]) |
3 |
长度 |
[1, 2, 3] + [4, 5, 6] |
[1, 2, 3, 4, 5, 6] |
组合 |
['Hi!'] * 4 |
['Hi!', 'Hi!', 'Hi!', 'Hi!'] |
重复 |
3 in [1, 2, 3] |
True |
元素是否存在于列表中 |
for x in [1, 2, 3]: print x, |
1 2 3 |
迭代 |
六、Python列表截取
Python的列表截取与字符串操作类型,如下所示:
复制代码代码如下:
L = ['spam', 'Spam', 'SPAM!']
操作:
Python 表达式 |
结果 |
描述 |
L[2] |
'SPAM!' |
读取列表中第三个元素 |
L[-2] |
'Spam' |
读取列表中倒数第二个元素 |
L[1:] |
['Spam', 'SPAM!'] |
从第二个元素开始截取列表 |
七、Python列表操作的函数和方法
列表操作包含以下函数:
1、cmp(list1, list2):比较两个列表的元素
2、len(list):列表元素个数
3、max(list):返回列表元素最大值
4、min(list):返回列表元素最小值
5、list(seq):将元组转换为列表
列表操作包含以下方法:
1、list.append(obj):在列表末尾添加新的对象
2、list.count(obj):统计某个元素在列表中出现的次数
3、list.extend(seq):在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
4、list.index(obj):从列表中找出某个值第一个匹配项的索引位置
5、list.insert(index, obj):将对象插入列表
6、list.pop(obj=list[-1]):移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
7、list.remove(obj):移除列表中某个值的第一个匹配项
8、list.reverse():反向列表中元素
9、list.sort([func]):对原列表进行排序
字典
一、什么是字典?
字典是Python语言中唯一的映射类型。
映射类型对象里哈希值(键,key)和指向的对象(值,value)是一对多的的关系,通常被认为是可变的哈希表。
字典对象是可变的,它是一个容器类型,能存储任意个数的Python对象,其中也可包括其他容器类型。
字典类型与序列类型的区别:
1.存取和访问数据的方式不同。
2.序列类型只用数字类型的键(从序列的开始按数值顺序索引);
3.映射类型可以用其他对象类型作键(如:数字、字符串、元祖,一般用字符串作键),和序列类型的键不同,映射类型的键直4.接或间接地和存储数据值相关联。
5.映射类型中的数据是无序排列的。这和序列类型是不一样的,序列类型是以数值序排列的。
6.映射类型用键直接“映射”到值。
字典是Python中最强大的数据类型之一。
二、如何创建字典和给字典赋值
简单地说字典就是用大括号包裹的键值对的集合。(键值对也被称作项)
一般形式:
复制代码代码如下:
adict = {}
adict = {key1:value2, key2:value2, …}
或用dict()函数,如,adict = dict() 或 adict = dict((['x',1],['y',2]))这样写对吗?adict = dict(['x',1],['y',2])。关键字参数创建字典,如:adict= dict(name='allen',age='40′)
或用fromkeys()方法,如,adict = {}.fromkeys((‘x','y'), -1) 这样创建的字典的value是一样的,若不给值,默认为None。
特点:
1、键与值用冒号“:”分开;
2、项与项用逗号“,”分开;
3、字典中的键必须是唯一的,而值可以不唯一。
复制代码代码如下:
adict = {‘name':'allen', ‘name':'lucy', ‘age':'40′} 与 bdict = {‘name':'allen', ‘name2′:'allen', ‘age':'40′}
注意:如果字典中的值为数字,最好使用字符串数字形式,如:'age':'040′ 而不用 ‘age':040
三、字典的基本操作
1、如何访问字典中的值?
adict[key] 形式返回键key对应的值value,如果key不在字典中会引发一个KeyError。
2、如何检查key是否在字典中?
a、has_key()方法 形如:adict.haskey(‘name') 有–>True,无–>False
b、in 、not in 形如:'name' in adict 有–>True,无–>False
3、如何更新字典?
a、添加一个数据项(新元素)或键值对
adict[new_key] = value 形式添加一个项
b、更新一个数据项(元素)或键值对
adict[old_key] = new_value
c、删除一个数据项(元素)或键值对
del adict[key] 删除键key的项 / del adict 删除整个字典
adict.pop(key) 删除键key的项并返回key对应的 value值
四、映射类型操作符
标准类型操作符(+,-,*,<,>,<=,>=,==,!=,and,or, not)
a、字典不支持拼接和重复操作符(+,*)
b、字典的比较操作
先比较字典的长度也就是字典的元素个数
键比较
值比较
例子:
复制代码代码如下:
adict = {}
bdict = {‘name':'allen', ‘age':'40′}
cmp(adict, bdict) < –>-1 or > –>1 or == –>0
五、映射相关的函数
1、len() 返回字典的长度
2、hash() 返回对象的哈希值,可以用来判断一个对象能否用来作为字典的键
3、dict() 工厂函数,用来创建字典
六、字典的方法
1、adict.keys() 返回一个包含字典所有KEY的列表;
2、adict.values() 返回一个包含字典所有value的列表;
3、adict.items() 返回一个包含所有(键,值)元祖的列表;
4、adict.clear() 删除字典中的所有项或元素;
5、adict.copy() 返回一个字典浅拷贝的副本;
6、adict.fromkeys(seq, val=None) 创建并返回一个新字典,以seq中的元素做该字典的键,val做该字典中所有键对应的初始值(默认为None);
7、adict.get(key, default = None) 返回字典中key对应的值,若key不存在字典中,则返回default的值(default默认为None);
8、adict.has_key(key) 如果key在字典中,返回True,否则返回False。 现在用 in 、 not in;
9、adict.iteritems()、adict.iterkeys()、adict.itervalues() 与它们对应的非迭代方法一样,不同的是它们返回一个迭代子,而不是一个列表;
10、adict.pop(key[,default]) 和get方法相似。如果字典中存在key,删除并返回key对应的vuale;如果key不存在,且没有给出default的值,则引发keyerror异常;
11、adict.setdefault(key, default=None) 和set()方法相似,但如果字典中不存在Key键,由 adict[key] = default 为它赋值;
12、adict.update(bdict) 将字典bdict的键值对添加到字典adict中。
七、字典的遍历
1、遍历字典的key(键)
复制代码代码如下:
for key in adict.keys():print key
2、遍历字典的value(值)
复制代码代码如下:
for value in adict.values(): print value
3、遍历字典的项(元素)
复制代码代码如下:
for item in adict.items():print item
4、遍历字典的key-value
复制代码代码如下:
for item,value in adict.items(): print ‘key=%s, value=%s' %(item, value) 或 for item,value in adict.iteritems(): print ‘key=%s, value=%s' %(item, value)
集合
set 是一个无序的元素集合,支持并、交、差及对称差等数学运算, 但由于 set 不记录元素位置,因此不支持索引、分片等类序列的操作。
初始化
复制代码代码如下:
s0 = set()
d0 = {}
s1 = {0}
s2 = {i % 2 for i in range(10)}
s = set('hi')
t = set(['h', 'e', 'l', 'l', 'o'])
print(s0, s1, s2, s, t, type(d0))
运行结果:
复制代码代码如下:
set() {0} {0, 1} {'i', 'h'} {'e', 'o', 'l', 'h'} <class 'dict'>
提示
1.s0、d0:使用 {} 只能创建空字典,创建空集必须用 set();
2.ss、sl:set 中的元素是 无序不重复 的,可以利用这个特点去除列表中的重复元素。
运算操作
复制代码代码如下:
print(s.intersection(t), s & t) # 交集
print(s.union(t), s | t) # 并集
print(s.difference(t), s - t) # 差集
print(s.symmetric_difference(t), s ^ t) # 对称差集
print(s1.issubset(s2), s1 <= s2) # 子集
print(s1.issuperset(s2), s1 >= s2) # 包含
运行结果:
复制代码代码如下:
{'h'} {'h'}
{'l', 'h', 'i', 'o', 'e'} {'l', 'h', 'i', 'o', 'e'}
{'i'} {'i'}
{'i', 'l', 'o', 'e'} {'i', 'l', 'o', 'e'}
True True
False False
提示
1.非运算符的方法接受任何可迭代对象作为参数,如 s.update([0, 1]);
2.其他等价操作:s.update(t) 与 s |= t,s.intersection_update(t) 与 s &= t,s.difference_update(t) 与 s -= t,s.symmetric_difference_update(t) 与 s ^= t 等。
基本方法
复制代码代码如下:
s = {0}
print(s, len(s)) # 获取集合中的元素的总数
s.add("x") # 添加一个元素
print(s)
s.update([1,2,3]) # 添加多个元素
print(s, "x" in s) # 成员资格测试
s.remove("x") # 去掉一个元素
print(s, "x" not in s)
s.discard("x") # 如果集合存在指定元素,则删除该元素
c = s.copy() # 复制集合
print(s, s.pop()) # 弹出集合中的一个不确定元素,如果原集合为空则引发 KeyError
s.clear() # 删除集合中的元素
print(s, c)
运行结果:
复制代码代码如下:
{0} 1
{0, 'x'}
{0, 'x', 1, 2, 3} True
{0, 1, 2, 3} True
{1, 2, 3} 0
set() {0, 1, 2, 3}
Str字符串方法
1、去空格及特殊符号
复制代码代码如下:
s.strip().lstrip().rstrip(',')
2、复制字符串
复制代码代码如下:
#strcpy(sStr1,sStr2)
sStr1 = 'strcpy'
sStr2 = sStr1
sStr1 = 'strcpy2'
print sStr2
3、连接字符串
复制代码代码如下:
#strcat(sStr1,sStr2)
sStr1 = 'strcat'
sStr2 = 'append'
sStr1 += sStr2
print sStr1
4、查找字符
复制代码代码如下:
#strchr(sStr1,sStr2)
# < 0 为未找到
sStr1 = 'strchr'
sStr2 = 's'
nPos = sStr1.index(sStr2)
print nPos
5、比较字符串
复制代码代码如下:
#strcmp(sStr1,sStr2)
sStr1 = 'strchr'
sStr2 = 'strch'
print cmp(sStr1,sStr2)
6、扫描字符串是否包含指定的字符
复制代码代码如下:
#strspn(sStr1,sStr2)
sStr1 = '12345678'
sStr2 = '456'
#sStr1 and chars both in sStr1 and sStr2
print len(sStr1 and sStr2)
7、字符串长度
复制代码代码如下:
#strlen(sStr1)
sStr1 = 'strlen'
print len(sStr1)
8、将字符串中的大小写转换
复制代码代码如下:
S.lower() #小写
S.upper() #大写
S.swapcase() #大小写互换
S.capitalize() #首字母大写
String.capwords(S) #这是模块中的方法。它把S用split()函数分开,然后用capitalize()把首字母变成大写,最后用join()合并到一起
#实例:
#strlwr(sStr1)
sStr1 = 'JCstrlwr'
sStr1 = sStr1.upper()
#sStr1 = sStr1.lower()
print sStr1
9、追加指定长度的字符串
复制代码代码如下:
#strncat(sStr1,sStr2,n)
sStr1 = '12345'
sStr2 = 'abcdef'
n = 3
sStr1 += sStr2[0:n]
print sStr1
10、字符串指定长度比较
复制代码代码如下:
#strncmp(sStr1,sStr2,n)
sStr1 = '12345'
sStr2 = '123bc'
n = 3
print cmp(sStr1[0:n],sStr2[0:n])
11、复制指定长度的字符
复制代码代码如下:
#strncpy(sStr1,sStr2,n)
sStr1 = ''
sStr2 = '12345'
n = 3
sStr1 = sStr2[0:n]
print sStr1
12、将字符串前n个字符替换为指定的字符
复制代码代码如下:
#strnset(sStr1,ch,n)
sStr1 = '12345'
ch = 'r'
n = 3
sStr1 = n * ch + sStr1[3:]
print sStr1
13、扫描字符串
复制代码代码如下:
#strpbrk(sStr1,sStr2)
sStr1 = 'cekjgdklab'
sStr2 = 'gka'
nPos = -1
for c in sStr1:
if c in sStr2:
nPos = sStr1.index(c)
break
print nPos
14、翻转字符串
复制代码代码如下:
#strrev(sStr1)
sStr1 = 'abcdefg'
sStr1 = sStr1[::-1]
print sStr1
15、查找字符串
复制代码代码如下:
#strstr(sStr1,sStr2)
sStr1 = 'abcdefg'
sStr2 = 'cde'
print sStr1.find(sStr2)
16、分割字符串
复制代码代码如下:
#strtok(sStr1,sStr2)
sStr1 = 'ab,cde,fgh,ijk'
sStr2 = ','
sStr1 = sStr1[sStr1.find(sStr2) + 1:]
print sStr1
#或者
s = 'ab,cde,fgh,ijk'
print(s.split(','))
17、连接字符串
复制代码代码如下:
delimiter = ','
mylist = ['Brazil', 'Russia', 'India', 'China']
print delimiter.join(mylist)
18、PHP 中 addslashes 的实现
复制代码代码如下:
def addslashes(s):
d = {'"':'\\"', "'":"\\'", "\0":"\\\0", "\\":"\\\\"}
return ''.join(d.get(c, c) for c in s)
s = "John 'Johny' Doe (a.k.a. \"Super Joe\")\\\0"
print s
print addslashes(s)
19、只显示字母与数字
复制代码代码如下:
def OnlyCharNum(s,oth=''):
s2 = s.lower();
fomart = 'abcdefghijklmnopqrstuvwxyz0123456789'
for c in s2:
if not c in fomart:
s = s.replace(c,'');
return s;
print(OnlyStr("a000 aa-b"))
20、截取字符串
复制代码代码如下:
str = '0123456789′
print str[0:3] #截取第一位到第三位的字符
print str[:] #截取字符串的全部字符
print str[6:] #截取第七个字符到结尾
print str[:-3] #截取从头开始到倒数第三个字符之前
print str[2] #截取第三个字符
print str[-1] #截取倒数第一个字符
print str[::-1] #创造一个与原字符串顺序相反的字符串
print str[-3:-1] #截取倒数第三位与倒数第一位之前的字符
print str[-3:] #截取倒数第三位到结尾
print str[:-5:-3] #逆序截取,具体啥意思没搞明白?
21、字符串在输出时的对齐
复制代码代码如下:
S.ljust(width,[fillchar])
#输出width个字符,S左对齐,不足部分用fillchar填充,默认的为空格。
S.rjust(width,[fillchar]) #右对齐
S.center(width, [fillchar]) #中间对齐
S.zfill(width) #把S变成width长,并在右对齐,不足部分用0补足
22、字符串中的搜索和替换
复制代码代码如下:
S.find(substr, [start, [end]])
#返回S中出现substr的第一个字母的标号,如果S中没有substr则返回-1。start和end作用就相当于在S[start:end]中搜索
S.index(substr, [start, [end]])
#与find()相同,只是在S中没有substr时,会返回一个运行时错误
S.rfind(substr, [start, [end]])
#返回S中最后出现的substr的第一个字母的标号,如果S中没有substr则返回-1,也就是说从右边算起的第一次出现的substr的首字母标号
S.rindex(substr, [start, [end]])
S.count(substr, [start, [end]]) #计算substr在S中出现的次数
S.replace(oldstr, newstr, [count])
#把S中的oldstar替换为newstr,count为替换次数。这是替换的通用形式,还有一些函数进行特殊字符的替换
S.strip([chars])
#把S中前后chars中有的字符全部去掉,可以理解为把S前后chars替换为None
S.lstrip([chars])
S.rstrip([chars])
S.expandtabs([tabsize])
#把S中的tab字符替换没空格,每个tab替换为tabsize个空格,默认是8个
23、字符串的分割和组合
复制代码代码如下:
S.split([sep, [maxsplit]])
#以sep为分隔符,把S分成一个list。maxsplit表示分割的次数。默认的分割符为空白字符
S.rsplit([sep, [maxsplit]])
S.splitlines([keepends])
#把S按照行分割符分为一个list,keepends是一个bool值,如果为真每行后而会保留行分割符。
S.join(seq) #把seq代表的序列──字符串序列,用S连接起来
24、字符串的mapping,这一功能包含两个函数
复制代码代码如下:
String.maketrans(from, to)
#返回一个256个字符组成的翻译表,其中from中的字符被一一对应地转换成to,所以from和to必须是等长的。
S.translate(table[,deletechars])
# 使用上面的函数产后的翻译表,把S进行翻译,并把deletechars中有的字符删掉。需要注意的是,如果S为unicode字符串,那么就不支持 deletechars参数,可以使用把某个字符翻译为None的方式实现相同的功能。此外还可以使用codecs模块的功能来创建更加功能强大的翻译表。
25、字符串还有一对编码和解码的函数
复制代码代码如下:
S.encode([encoding,[errors]])
# 其中encoding可以有多种值,比如gb2312 gbk gb18030 bz2 zlib big5 bzse64等都支持。errors默认值为"strict",意思是UnicodeError。可能的值还有'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' 和所有的通过codecs.register_error注册的值。这一部分内容涉及codecs模块,不是特明白
S.decode([encoding,[errors]])
26、字符串的测试、判断函数,这一类函数在string模块中没有,这些函数返回的都是bool值
复制代码代码如下:
S.startswith(prefix[,start[,end]])
#是否以prefix开头
S.endswith(suffix[,start[,end]])
#以suffix结尾
S.isalnum()
#是否全是字母和数字,并至少有一个字符
S.isalpha() #是否全是字母,并至少有一个字符
S.isdigit() #是否全是数字,并至少有一个字符
S.isspace() #是否全是空白字符,并至少有一个字符
S.islower() #S中的字母是否全是小写
S.isupper() #S中的字母是否便是大写
S.istitle() #S是否是首字母大写的
27、字符串类型转换函数,这几个函数只在string模块中有
复制代码代码如下:
string.atoi(s[,base])
#base默认为10,如果为0,那么s就可以是012或0x23这种形式的字符串,如果是16那么s就只能是0x23或0X12这种形式的字符串
string.atol(s[,base]) #转成long
string.atof(s[,base]) #转成float
tuple元组方法
一、创建元组
复制代码代码如下:
tup1 = ('physics', 'chemistry', 1997, 2000);
tup2 = (1, 2, 3, 4, 5 );
tup3 = "a", "b", "c", "d";
创建空元组
复制代码代码如下:
tup1 = ();
元组中只包含一个元素时,需要在元素后面添加逗号来消除歧义
复制代码代码如下:
tup1 = (50,);
元组与字符串类似,下标索引从0开始,可以进行截取,组合等。
二、访问元组
元组可以使用下标索引来访问元组中的值,如下实例:
复制代码代码如下:
#!/usr/bin/python
tup1 = ('physics', 'chemistry', 1997, 2000);
tup2 = (1, 2, 3, 4, 5, 6, 7 );
print "tup1[0]: ", tup1[0]
print "tup2[1:5]: ", tup2[1:5]
#以上实例输出结果:
#tup1[0]: physics
#tup2[1:5]: [2, 3, 4, 5]
三、修改元组
元组中的元素值是不允许修改的,但我们可以对元组进行连接组合,如下实例:
复制代码代码如下:
#!/usr/bin/python
tup1 = (12, 34.56);
tup2 = ('abc', 'xyz');
# 以下修改元组元素操作是非法的。
# tup1[0] = 100;
# 创建一个新的元组
tup3 = tup1 + tup2;
print tup3;
#以上实例输出结果:
#(12, 34.56, 'abc', 'xyz')
四、删除元组
元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组,如下实例:
复制代码代码如下:
#!/usr/bin/python
tup = ('physics', 'chemistry', 1997, 2000);
print tup;
del tup;
print "After deleting tup : "
print tup;
#以上实例元组被删除后,输出变量会有异常信息,输出如下所示:
#('physics', 'chemistry', 1997, 2000)
#After deleting tup :
#Traceback (most recent call last):
# File "test.py", line 9, in <module>
# print tup;
#NameError: name 'tup' is not defined[/code]
五、元组运算符
与字符串一样,元组之间可以使用 + 号和 * 号进行运算。这就意味着他们可以组合和复制,运算后会生成一个新的元组。
六、元组索引,截取
因为元组也是一个序列,所以我们可以访问元组中的指定位置的元素,也可以截取索引中的一段元素,如下所示:
元组:
复制代码代码如下:
L = ('spam', 'Spam', 'SPAM!')
七、无关闭分隔符
任意无符号的对象,以逗号隔开,默认为元组,如下实例:
复制代码代码如下:
#!/usr/bin/python
print 'abc', -4.24e93, 18+6.6j, 'xyz';
x, y = 1, 2;
print "Value of x , y : ", x,y;
以上实例允许结果:
复制代码代码如下:
abc -4.24e+93 (18+6.6j) xyz
Value of x , y : 1 2
八、元组内置函数
Python元组包含了以下内置函数
1、cmp(tuple1, tuple2):比较两个元组元素。
2、len(tuple):计算元组元素个数。
3、max(tuple):返回元组中元素最大值。
4、min(tuple):返回元组中元素最小值。
5、tuple(seq):将列表转换为元组。
九、另一种解读
tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出同学的名字:
复制代码代码如下:
>>> classmates = ('Michael', 'Bob', 'Tracy')
现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用classmates[0],classmates[-1],但不能赋值成另外的元素。
不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。
tuple的陷阱:当你定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来,比如:
复制代码代码如下:
>>> t = (1, 2)
>>> t
(1, 2)
如果要定义一个空的tuple,可以写成():
复制代码代码如下:
>>> t = ()
>>> t
()
但是,要定义一个只有1个元素的tuple,如果你这么定义:
复制代码代码如下:
>>> t = (1)
>>> t
1
定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。
所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义:
复制代码代码如下:
>>> t = (1,)
>>> t
(1,)
Python在显示只有1个元素的tuple时,也会加一个逗号,,以免你误解成数学计算意义上的括号。
在来看一个“可变的”tuple:
复制代码代码如下:
>>> t = ('a', 'b', ['A', 'B'])
>>> t[2][0] = 'X'
>>> t[2][1] = 'Y'
>>> t
('a', 'b', ['X', 'Y'])
这个tuple定义的时候有3个元素,分别是'a','b'和一个list。不是说tuple一旦定义后就不可变了吗?怎么后来又变了?
别急,我们先看看定义的时候tuple包含的3个元素:
当我们把list的元素'A'和'B'修改为'X'和'Y'后,tuple变为:
表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向'a',就不能改成指向'b',指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!
理解了“指向不变”后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变。