Table of Contents
-
- 1 對(duì)Python的理解(對(duì)比其他語言)
- 2 什么是Python的命名空間
- 3 Python中的pass語句
- 4 Python異常處理的用法和作用
- 5 Python的函數(shù)參數(shù)傳遞
- 6 函數(shù)的參數(shù)用法和注意事項(xiàng)
- 7 可變對(duì)象和不可變對(duì)象
- 8 def是運(yùn)行時(shí)執(zhí)行語句,并且是賦值語句
- 9 Python是否能以可變對(duì)象做函數(shù)默認(rèn)參數(shù)
- 10 企圖在函數(shù)中修改全局變量,沒有使用global,而創(chuàng)建了本地變量
- 11 對(duì)象的dir屬性和dict屬性
- 12 @staticmethod和@classmethod
- 13 使用property創(chuàng)建可管理的對(duì)象屬性
- 14 類屬性和實(shí)例屬性
- 15 Python自省
- 16 字典解析睦优、列表解析佃扼、集合解析
- 17 Python中單下劃線和雙下劃線
- 18 字符串格式化:\x和.format
- 19 正則表達(dá)式相關(guān)知識(shí)及字符串操作
- 20 迭代器和生成器
- 21 args and <code>*kwargs</code>
- 22 裝飾器
- 23 Python中重載
- 24 new和<code>init</code>的區(qū)別
- 25 單例模式
- 26 Python中的作用域
- 27 GIL線程全局鎖
- 28 協(xié)程
- 29 閉包
- 30 lambda函數(shù)
- 31 Python函數(shù)式編程
- 32 Python里的拷貝
- 33 Python是如何進(jìn)行內(nèi)存管理的
- 34 Python的List和Dict的實(shí)現(xiàn)原理
- 35 Python的is
- 36 read,readline和readlines
- 37 Python2和3的區(qū)別
- 38 Python的編碼問題
-
- 1 列表復(fù)制問題
- 2 求列表第三大的那個(gè)值
- 3 實(shí)現(xiàn)一個(gè)隊(duì)列
- 4 實(shí)現(xiàn)一個(gè)堆棧
- 5 用Python實(shí)現(xiàn)一個(gè)單向鏈表
- 6 用Python實(shí)現(xiàn)一個(gè)雙向鏈表
- 7 臺(tái)階問題/斐波那契
- 8 變態(tài)臺(tái)階問題
- 9 去除列表中的重復(fù)元素
- 10 創(chuàng)建字典的方法
- 11 合并兩個(gè)有序列表
- 12 歸并排序
- 13 質(zhì)數(shù)和日期問題
- 14 二分查找
- 15 打印文件夾
- 16 找零問題
- 17 前中后序遍歷
- 18 求最大樹深
- 19 求兩棵樹是否相同
- 20 前序中序求后序
- 21 廣度遍歷和深度遍歷二叉樹
- 22 快排
- 23 層次遍歷
- 24 深度遍歷
Python語言特性
1 對(duì)Python的理解(對(duì)比其他語言)
下面是一些關(guān)鍵點(diǎn):
- Python是一種解釋型語言衷蜓。這就是說累提,與C語言和C的衍生語言不同,Python代碼在運(yùn)行之前不需要編譯磁浇。
- Python是動(dòng)態(tài)類型語言斋陪,指的是你在聲明變量時(shí),不需要說明變量的類型置吓。
- Python非常適合面向?qū)ο蟮木幊蹋∣OP)无虚,因?yàn)樗С滞ㄟ^組合(composition)與繼承(inheritance)的方式定義類(class)。
- Python中沒有訪問說明符(access specifier衍锚,類似C++中的public和private)友题,這么設(shè)計(jì)的依據(jù)是“大家都是成年人了”。
在Python語言中戴质,函數(shù)是第一類對(duì)象(first-class objects)度宦。這指的是它們可以被指定給變量,函數(shù)既能返回函數(shù)類型告匠,也可以接受函數(shù)作為輸入戈抄。類(class)也是第一類對(duì)象。
Python代碼編寫快凫海,但是運(yùn)行速度比編譯語言通常要慢呛凶。好在Python允許加入基于C語言編寫的擴(kuò)展,因此我們能夠優(yōu)化代碼行贪,消除瓶頸漾稀,這點(diǎn)通常是可以實(shí)現(xiàn)的。numpy就是一個(gè)很好地例子建瘫,它的運(yùn)行速度真的非痴负矗快,因?yàn)楹芏嗨阈g(shù)運(yùn)算其實(shí)并不是通過Python實(shí)現(xiàn)的啰脚。
Python用途非常廣泛——網(wǎng)絡(luò)應(yīng)用殷蛇,自動(dòng)化,科學(xué)建模橄浓,大數(shù)據(jù)應(yīng)用粒梦,等等。它也常被用作“膠水語言”荸实,幫助其他語言和組件改善運(yùn)行狀況匀们。
Python讓困難的事情變得容易,因此程序員可以專注于算法和數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)准给,而不用處理底層的細(xì)節(jié)泄朴。
補(bǔ)充
- Python彩蛋
import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
import __hello__
Hello world!
2 什么是Python的命名空間
在Python中重抖,所有的名字都存在于一個(gè)空間中,它們?cè)谠摽臻g中存在和被操作——這就是命名空間祖灰。
它就好像一個(gè)盒子钟沛,每一個(gè)變量名字都對(duì)應(yīng)裝著一個(gè)對(duì)象。當(dāng)查詢變量的時(shí)候局扶,會(huì)從該盒子里面尋找相應(yīng)的對(duì)象恨统。
3 Python中的pass語句
Pass是一個(gè)在Python中不會(huì)被執(zhí)行的語句。在復(fù)雜語句中详民,如果一個(gè)地方需要暫時(shí)被留白延欠,它常常被用于占位符。
4 Python異常處理的用法和作用
[參考廖雪峰](https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143191375461417a222c54b7e4d65b258f491c093a515000]
答:try…except…except…[else…][finally…)
執(zhí)行try下的語句沈跨,如果引發(fā)異常,則執(zhí)行過程會(huì)跳到except語句兔综。對(duì)每個(gè)except分支順序嘗試執(zhí)行饿凛,如果引發(fā)的異常與except中的異常組匹配,執(zhí)行相應(yīng)的語句软驰。
如果所有的except都不匹配涧窒,則異常會(huì)傳遞到下一個(gè)調(diào)用本代碼的最高層try代碼中。
try下的語句正常執(zhí)行锭亏,則執(zhí)行else塊代碼纠吴。如果發(fā)生異常,就不會(huì)執(zhí)行
如果存在finally語句慧瘤,最后總是會(huì)執(zhí)行戴已。
try:
print('try...')
r = 10 / int('2')
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
else:
print('no error!')
finally:
print('finally...')
print('END')
5 Python的函數(shù)參數(shù)傳遞
看兩個(gè)例子:
a = 1
def fun(a):
a = 2
fun(a)
print a # 1
a = []
def fun(a):
a.append(1)
fun(a)
print a # [1]
所有的變量都可以理解是內(nèi)存中一個(gè)對(duì)象的“引用”
通過id
來看引用a
的內(nèi)存地址可以比較理解:
a = 1
def fun(a):
print "func_in",id(a) # func_in 41322472
a = 2
print "re-point",id(a), id(2) # re-point 41322448 41322448
print "func_out",id(a), id(1) # func_out 41322472 41322472
fun(a)
print a # 1
注:具體的值在不同電腦上運(yùn)行時(shí)可能不同。
可以看到锅减,在執(zhí)行完a = 2
之后糖儡,a
引用中保存的值,即內(nèi)存地址發(fā)生變化怔匣,由原來1
對(duì)象的所在的地址變成了2
這個(gè)實(shí)體對(duì)象的內(nèi)存地址握联。
而第2個(gè)例子a
引用保存的內(nèi)存值就不會(huì)發(fā)生變化:
a = []
def fun(a):
print "func_in",id(a) # func_in 53629256
a.append(1)
print "func_out",id(a) # func_out 53629256
fun(a)
print a # [1]
這里記住的是類型是屬于對(duì)象的,而不是變量每瞒。而對(duì)象有兩種,“可變”(mutable)與“不可變”(immutable)對(duì)象金闽。在python中,string, tuple, 和number是不可更改的對(duì)象剿骨,而 list, dict, set 等則是可以修改的對(duì)象代芜。(這就是這個(gè)問題的重點(diǎn))
當(dāng)一個(gè)引用傳遞給函數(shù)的時(shí)候,函數(shù)自動(dòng)復(fù)制一份引用,這個(gè)函數(shù)里的引用和外邊的引用沒有半毛關(guān)系了.所以第一個(gè)例子里函數(shù)把引用指向了一個(gè)不可變對(duì)象,當(dāng)函數(shù)返回的時(shí)候,外面的引用沒半毛感覺.而第二個(gè)例子就不一樣了,函數(shù)內(nèi)的引用指向的是可變對(duì)象,對(duì)它的操作就和定位了指針地址一樣,在內(nèi)存里進(jìn)行修改.
如果還不明白的話,這里有更好的解釋: http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference
6 函數(shù)的參數(shù)用法和注意事項(xiàng)
(參考廖雪峰課程)[https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431752945034eb82ac80a3e64b9bb4929b16eeed1eb9000]
函數(shù)參數(shù)分為位置參數(shù)、默認(rèn)參數(shù)懦砂、可變參數(shù)蜒犯、關(guān)鍵字參數(shù)组橄、命名關(guān)鍵字參數(shù)(定義和調(diào)用必須按順序傳入)
numbers=[1,2,3,4,5]
def sum(*args):
sum=0
for i in args:
sum = sum+i*i
return sum
sum(*numbers)
dict1={'a':1,'b':2}
def f(**kwargs):
for k,v in kwargs.items():
print('{0}:{1}'.format(k,v))
f(**dict1)
# 如果需要約束傳入的關(guān)鍵字參數(shù)的名稱,可以用命名關(guān)鍵字參數(shù)
# 命名關(guān)鍵字參數(shù)必須傳入?yún)?shù)名罚随,這和位置參數(shù)不同玉工。
def person(name, age, *, city, job):
print(name, age, city, job)
def person(name, age, *args, city, job):
print(name, age, args, city, job)
# 命名關(guān)鍵字參數(shù)可以有缺省值,從而簡(jiǎn)化調(diào)用:
def person(name, age, *, city='Beijing', job):
print(name, age, city, job)
7 可變對(duì)象和不可變對(duì)象
- python所有數(shù)字類型(布爾樹,整數(shù),浮點(diǎn)數(shù),復(fù)數(shù))均為不可變對(duì)象,
- 可變對(duì)象:file,dict,set,list,bytesarray,range
- 不可變對(duì)象:boolean,int,float,complex,tuple,str,bytes,frozenset
- 有序sequence:str,list,tuple,OrderedDict,
- 無序:dict,set,
- 不可重復(fù):set,tuple
- 可變對(duì)象(mutable object)has no hash value
- 不可變對(duì)象可哈希,hashable
8 def是運(yùn)行時(shí)執(zhí)行語句,并且是賦值語句
類和對(duì)象均為第一類對(duì)象淘菩,調(diào)用的時(shí)候才會(huì)運(yùn)行
9 Python是否能以可變對(duì)象做函數(shù)默認(rèn)參數(shù)
不可以,字典,集合,列表等可變對(duì)象不適合作為函數(shù)默認(rèn)值
要不然第二次調(diào)用時(shí),一次調(diào)用的默認(rèn)參數(shù)的值會(huì)影響二次調(diào)用.
def f(l=[]):
for i in range(3):
l.append(i)
return l
f(l=[2]),---- l=[2,0,1,2]
f(), ---- l=[0,1,2]
f(), ---- l=[0,1,2,0,1,2]
10 企圖在函數(shù)中修改全局變量,沒有使用global,而創(chuàng)建了本地變量
修改全局變量需要global聲明,要不然會(huì)創(chuàng)建同名的本地變量.
11 對(duì)象的dir屬性和dict屬性
Python一切皆對(duì)象遵班,每個(gè)對(duì)象都有自己獨(dú)特的屬性和方法
dir()函數(shù)會(huì)自動(dòng)尋找一個(gè)對(duì)象的所有屬性,包括dict中的屬性潮改。
dict是dir()的子集狭郑,dir()包含dict中的屬性。
12 @staticmethod和@classmethod
Python其實(shí)有3個(gè)方法,即靜態(tài)方法(staticmethod),類方法(classmethod)和實(shí)例方法,如下:
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()
這里先理解下函數(shù)參數(shù)里面的self和cls.這個(gè)self和cls是對(duì)類或者實(shí)例的綁定,對(duì)于一般的函數(shù)來說我們可以這么調(diào)用foo(x)
,這個(gè)函數(shù)就是最常用的,它的工作跟任何東西(類,實(shí)例)無關(guān).對(duì)于實(shí)例方法,我們知道在類里每次定義方法的時(shí)候都需要綁定這個(gè)實(shí)例,就是foo(self, x)
,為什么要這么做呢?因?yàn)閷?shí)例方法的調(diào)用離不開實(shí)例,我們需要把實(shí)例自己傳給函數(shù),調(diào)用的時(shí)候是這樣的a.foo(x)
(其實(shí)是foo(a, x)
).類方法一樣,只不過它傳遞的是類而不是實(shí)例,A.class_foo(x)
.注意這里的self和cls可以替換別的參數(shù),但是python的約定是這倆,還是不要改的好.
對(duì)于靜態(tài)方法其實(shí)和普通的方法一樣,不需要對(duì)誰進(jìn)行綁定,唯一的區(qū)別是調(diào)用的時(shí)候需要使用a.static_foo(x)
或者A.static_foo(x)
來調(diào)用.
\ | 實(shí)例方法 | 類方法 | 靜態(tài)方法 |
---|---|---|---|
a = A() | a.foo(x) | a.class_foo(x) | a.static_foo(x) |
A | 不可用 | A.class_foo(x) | A.static_foo(x) |
更多關(guān)于這個(gè)問題:
- http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
- https://realpython.com/blog/python/instance-class-and-static-methods-demystified/
13 使用property創(chuàng)建可管理的對(duì)象屬性
property可以讓實(shí)例在形式上是屬性訪問,但實(shí)際上調(diào)用方法
class Circle2(object):
def __init__(self, radius):
self.radius = radius
def getRadius(self):
# return self.radius
return round(self.radius, 2) # 表示四舍五入后保留小數(shù)點(diǎn)后兩位
def setRadius(self, value):
if not isinstance(value, (int, long, float)):
raise valueError('wrong type .')
self.radius = float(value)
def getArea(self):
return self.radius * 2 * pi
R = property(getRadius, setRadius)
r = Circle2(3.2)
print(r.R) # 自動(dòng)調(diào)用getRadius
r.R = 5.4 # 自動(dòng)調(diào)用setRadius
print(r.R) # 自動(dòng)調(diào)用getRadius
14 類屬性和實(shí)例屬性
:
? 是可在類的所有實(shí)例之間共享的值(也就是說汇在,它們不是單獨(dú)分配給每個(gè)實(shí)例的)翰萨。例如下例中,num_of_instance 就是類屬性糕殉,用于跟蹤存在著多少個(gè)Test 的實(shí)例亩鬼。
實(shí)例屬性:
實(shí)例化之后,每個(gè)實(shí)例單獨(dú)擁有的變量阿蝶。
class Test(object):
num_of_instance = 0
def __init__(self, name):
self.name = name
Test.num_of_instance += 1
if __name__ == '__main__':
print Test.num_of_instance # 0
t1 = Test('jack')
print Test.num_of_instance # 1
t2 = Test('lucy')
print t1.name , t1.num_of_instance # jack 2
print t2.name , t2.num_of_instance # lucy 2
補(bǔ)充的例子
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"
是實(shí)例調(diào)用了類屬性,這其實(shí)和上面第一個(gè)問題一樣,就是函數(shù)傳參的問題,p1.name
一開始是指向的類屬性name="aaa"
,但是在實(shí)例的作用域里把類屬性的引用改變了,就變成了一個(gè)實(shí)例屬性,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://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block
15 Python自省
這個(gè)也是python彪悍的特性.
自省就是面向?qū)ο蟮恼Z言所寫的程序在運(yùn)行時(shí),所能知道對(duì)象的類型.簡(jiǎn)單一句就是運(yùn)行時(shí)能夠獲得對(duì)象的類型.比如type(),dir(),getattr(),hasattr(),isinstance().
a = [1,2,3]
b = {'a':1,'b':2,'c':3}
c = True
print type(a),type(b),type(c) # <type 'list'> <type 'dict'> <type 'bool'>
print isinstance(a,list) # True
16 字典解析雳锋、列表解析、集合解析
代碼示例如下:
list1=[x for x in range(100) if x%2==0] #或 [x for x in range(0,100,2)]
L = list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
L2 = list(filter(lambda x: x > 0, [1. - 1, -3, -4, 3, 3, 45, 34]))
#集合的列表生成式
s={1,34,5,-7,6,87,-8,-9,11}
print({x for x in s if x%3==0})
#補(bǔ)充:集合的交集并集等操作
A=set([randint(1,20) for _ in range(10)])
B=set([randint(1,20) for _ in range(10)])
print(A&B,A|B,A-B,A^B) #交羡洁,并玷过,差,補(bǔ)
d = {key: value for (key, value) in iterable if key**}
#補(bǔ)充 如何根據(jù)字典中值的大小,對(duì)字典中的項(xiàng)排序
#方案1 使用zip將字典數(shù)據(jù)轉(zhuǎn)化為元組
score = {
'LiLei': 79,
'Jim': 88,
'Lucy': 92
}
score4 = tuple(zip(score.values(),score.keys()))
score5 = sorted(score4)
##直接用sorted,
print(sorted(score.items(),key=lambda x:x[1])) #表示對(duì)生成的列表的元組索引第二位進(jìn)行排序
#補(bǔ)充 k,v交換
score2={v:k for k,v in score.items()}
score3=dict(zip(score2.values(),score2.keys()))
補(bǔ)充1 如何為元組的每個(gè)元素命名,提高程序可讀性
from collections import namedtuple
Student = namedtuple('Student', ['name', 'age', 'sex', 'email'])
Jim = Student('Jim', 16, 'male', 'jim8721@gamil.com')
print(Jim.name)
print(Jim.age)
print(Jim.sex)
print(Jim.email)
補(bǔ)充2 如何統(tǒng)計(jì)序列中元素的出現(xiàn)頻度
from collections import Counter, OrderedDict
from random import randint
import re
data = [randint(0, 20) for _ in range(30)] #產(chǎn)生30個(gè)0到20的隨機(jī)整數(shù)
print(Counter(data))
print(Counter(data).most_common(3))
補(bǔ)充3 如何快速找到多個(gè)字典中的公共鍵(key)
from functools import reduce
N1 = {
'蘇亞雷斯': 1,
'梅西': 2,
'本澤馬': 1,
'C羅': 3
}
N2 = {
'蘇亞雷斯': 2,
'C羅': 1,
'格里子曼': 2,
'貝爾': 1
}
N3 = {
'蘇亞雷斯': 1,
'托雷斯': 2,
'內(nèi)馬爾': 1,
'貝爾': 1
}
# 統(tǒng)計(jì)出每輪比賽都有進(jìn)球的球員
res = []
for k in N1:
if k in N2 and k in N3:
res.append(k)
print(res)
#解決方案:
'''
利用set集合的交集操作
1.使用dict的viewkeys()方法,返回一個(gè)dict.keys()的集合
2.使用map函數(shù),得到所有字典的keys的集合
3.使用reduce函數(shù),取所有字典的keys的集合的交集
'''
print(reduce(lambda x,y:x &y,list(map(dict.keys,[N1,N2,N3]))))
補(bǔ)充4 創(chuàng)建有序的字典
from functools import OrderedDict
od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
# 字典輸出可以按插入的順序排序并輸出
補(bǔ)充5 元組和列表的同異
同:列表與元組都是容器筑煮,是一系列的對(duì)象辛蚊。二者都可以包含任意類型的元素甚至可以是一個(gè)序列,還可以包含元素的順序(不像集合和字典)咆瘟。
元組屬于不可變對(duì)象嚼隘,列表屬于可變對(duì)象,列表的很多方法不適用于元組袒餐;元組可哈希而列表不可哈希飞蛹;元組占用空間更小,代碼的語義更好理解再函數(shù)式編程較常用灸眼。
17 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內(nèi)部的名字,用來區(qū)別其他用戶自定義的命名,以防沖突卧檐,就是例如__init__()
,__del__()
,__call__()
這些特殊方法
_foo
:一種約定,用來指定變量私有.程序員用來指定私有變量的一種方式.不能用from module import * 導(dǎo)入,其他方面和公有一樣訪問焰宣;
__foo
:這個(gè)有真正的意義:解析器用_classname__foo
來代替這個(gè)名字,以區(qū)別和其他類相同的命名,它無法直接像公有成員一樣隨便訪問,通過對(duì)象名._類名__xxx這樣的方式可以訪問.
或者: http://www.zhihu.com/question/19754941
18 字符串格式化:%和.format
.format在許多方面看起來更便利.對(duì)于%
最煩人的是它無法同時(shí)傳遞一個(gè)變量和元組.你可能會(huì)想下面的代碼不會(huì)有什么問題:
"hi there %s" % name
但是,如果name恰好是(1,2,3),它將會(huì)拋出一個(gè)TypeError異常.為了保證它總是正確的,你必須這樣做:
"hi there %s" % (name,) # 提供一個(gè)單元素的數(shù)組而不是一個(gè)參數(shù)
但是有點(diǎn)丑..format就沒有這些問題.你給的第二個(gè)問題也是這樣,.format好看多了.
你為什么不用它?
- 不知道它(在讀這個(gè)之前)
- 為了和Python2.5兼容(譬如logging庫建議使用
%
(issue #4))
http://stackoverflow.com/questions/5082452/python-string-formatting-vs-format
19 正則表達(dá)式相關(guān)知識(shí)及字符串操作
- 字符串拼接join方法
str.join(iterable)
L = ["<0112>", "<32>", "<1024x768>", 60, "<1>", "<100.0>", "<500.0>"]
print(''.join(str(x) for x in L))
- 如何判斷字符串a(chǎn)是否以字符串b開頭或結(jié)尾,str.startswith(),str.endswith()
a="abcdefg||fadfa.py"
a.endswith(('.py','.sh'))
- 如何用Python來進(jìn)行查詢和替換一個(gè)文本字符串霉囚?
s = '\tabd\t124\txyz\r\n'
print(re.sub('\t|\r|\n','',s))
- 一次性拆分字符串 re.split(),str.split()
"""
解決方案:
方法一:連續(xù)使用是str.split()方法,每次處理一種分隔符號(hào)
方法二:使用正則表達(dá)式的re.split()方法,一次性拆分字符串
"""
s = 'ab;cd|efg|hi,jklmn|topq;rst,uvw|txyz'
t = s.split(';')
t1 = re.split(r'[,;|\t]+',s)
- Python里面match()和search()的區(qū)別?
re模塊中match(pattern,string[,flags]),檢查string的開頭是否與pattern匹配匕积。
re模塊中re.search(pattern,string[,flags]),在string搜索pattern的第一個(gè)匹配值盈罐。
- Python re.findall()方法
#尋找一段字符串中的11位數(shù)字(手機(jī)號(hào))榜跌,返回列表
import re
str1="13832244324gdsjsfhauer13632996133"
re.findall(r'\d{11}',str1)
- 用Python匹配HTML tag的時(shí)候,<.>和<.?>有什么區(qū)別盅粪?
答:術(shù)語叫貪婪匹配( <.> )和非貪婪匹配(<.?> )
前者是貪婪匹配钓葫,會(huì)從頭到尾匹配 <a>xyz</a>,而后者是非貪婪匹配票顾,只匹配到第一個(gè) >础浮。
- 如何去掉字符串中不需要的字符
"""
解決方案:
方法1:字符串strip(),lstrip(),rstrip()方法去掉字符串兩段字符
方法2:刪除單個(gè)固定位置的字符,可以使用切片+拼接的方式
方法3:字符串的replace()方法或正則表達(dá)式re.sub()刪除任意位置字符
方法4:字符串translate()方法,可以同時(shí)刪除多種不同字符
"""
s=' nick2008@gmail.com '
print(s.strip(' '))
print('----------------')
s = '====+-----'
print(s.strip('-='))
print('----------------')
s=' nick2008 @gmail.com '
print(s[2:11]+s[12:23])
print('----------------')
s = '\tabd\t124\txyz\r\n'
print(s.replace('\t',''))
print('----------------')
s = '\tabd\t124\txyz\r\n'
print(re.sub('\t|\r|\n','',s))
print('----------------')
s = '\tabd\t124\txyz\r\n'
print(s.translate(None,'\t\r\n'))
s = '\tabd\t124\txyz\r\n'
print(s.replace('\t',''))
u = u'uulàlà,là,māmá'
print u.translate(dict.fromkeys([0x0,0x0101,0x1]))
- 補(bǔ)充 單引號(hào),雙引號(hào)奠骄,三引號(hào)的區(qū)別
答:?jiǎn)我?hào)和雙引號(hào)是等效的豆同,如果要換行,需要符號(hào)(),三引號(hào)則可以直接換行含鳞,并且可以包含注釋
如果要表示Let’s go 這個(gè)字符串
單引號(hào):s4 = ‘Let\’s go’
雙引號(hào):s5 = “Let’s go”
s6 = ‘I realy like“python”!’
這就是單引號(hào)和雙引號(hào)都可以表示字符串的原因了
20 迭代器和生成器
這個(gè)是stackoverflow里python排名第一的問題,值得一看: http://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python
這是中文版: http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/1/README.html
這里有個(gè)關(guān)于生成器的創(chuàng)建問題面試官有考:
問: 將列表生成式中[]改成() 之后數(shù)據(jù)結(jié)構(gòu)是否改變珍策?
答案:是姑隅,從列表變?yōu)樯善?/p>
>>> L = [x*x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x0000028F8B774200>
通過列表生成式圆裕,可以直接創(chuàng)建一個(gè)列表胳蛮。但是烫堤,受到內(nèi)存限制躯砰,列表容量肯定是有限的活箕。而且魂仍,創(chuàng)建一個(gè)包含百萬元素的列表沃但,不僅是占用很大的內(nèi)存空間磁滚,如:我們只需要訪問前面的幾個(gè)元素,后面大部分元素所占的空間都是浪費(fèi)的宵晚。因此垂攘,沒有必要?jiǎng)?chuàng)建完整的列表(節(jié)省大量?jī)?nèi)存空間)。在Python中淤刃,我們可以采用生成器:邊循環(huán)晒他,邊計(jì)算的機(jī)制—>generator
大數(shù)據(jù)的文件讀取
with open(path,'rb') as file:
for line in file:
print(file)
yield語句的用法
相當(dāng)于給函數(shù)運(yùn)行打斷點(diǎn),下次循環(huán)或者調(diào)用時(shí)在這里終止程序
yield簡(jiǎn)單說來就是一個(gè)生成器逸贾,這樣函數(shù)它記住上次返 回時(shí)在函數(shù)體中的位置陨仅。對(duì)生成器第 二次(或n 次)調(diào)用跳轉(zhuǎn)至該函樹)調(diào)用跳轉(zhuǎn)至該函數(shù)。
21 *args
and **kwargs
用*args
和**kwargs
只是為了方便并沒有強(qiáng)制使用它們.
當(dāng)你不確定你的函數(shù)里將要傳遞多少參數(shù)時(shí)你可以用*args
.例如,它可以傳遞任意數(shù)量的參數(shù):
>>> 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
允許你使用沒有事先定義的參數(shù)名:
>>> 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
你也可以混著用.命名參數(shù)首先獲得參數(shù)值然后所有的其他參數(shù)都傳遞給*args
和**kwargs
.命名參數(shù)在列表的最前端.例如:
def table_things(titlestring, **kwargs)
*args
和**kwargs
可以同時(shí)在函數(shù)的定義中,但是*args
必須在**kwargs
前面.
當(dāng)調(diào)用函數(shù)時(shí)你也可以用*
和**
語法.例如:
>>> 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
就像你看到的一樣,它可以傳遞列表(或者元組)的每一項(xiàng)并把它們解包.注意必須與它們?cè)诤瘮?shù)里的參數(shù)相吻合.當(dāng)然,你也可以在函數(shù)定義或者函數(shù)調(diào)用時(shí)用*.
http://stackoverflow.com/questions/3394835/args-and-kwargs
22 裝飾器
裝飾器是一個(gè)很著名的設(shè)計(jì)模式铝侵,經(jīng)常被用于有切面需求的場(chǎng)景灼伤,較為經(jīng)典的有計(jì)時(shí)統(tǒng)計(jì)、插入日志咪鲜、緩存計(jì)算結(jié)果狐赡、性能測(cè)試、事務(wù)處理等疟丙。裝飾器是解決這類問題的絕佳設(shè)計(jì)颖侄,有了裝飾器鸟雏,我們就可以抽離出大量函數(shù)中與函數(shù)功能本身無關(guān)的雷同代碼并繼續(xù)重用。概括的講览祖,裝飾器的作用就是為已經(jīng)存在的對(duì)象添加額外的功能孝鹊。
裝飾器的作用和功能:
- 引入日志
- 函數(shù)執(zhí)行時(shí)間統(tǒng)計(jì)
- 執(zhí)行函數(shù)前預(yù)備處理
- 執(zhí)行函數(shù)后的清理功能
- 權(quán)限校驗(yàn)等場(chǎng)景
- 緩存
下面舉例說明
裝飾器用做日志記錄
from functools import wrapper
def log(func):
@functools.wraps(func) # 將func的屬性傳遞給wrapper
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
f=func(*args, **kw)
print('end call %s():' % func.__name__)
return f
return wrapper
如何定義帶參數(shù)的裝飾器
import functools
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
# 同時(shí)支持@log和@log('execute')
def log2(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
if isinstance(text,str):
print('%s %s():' % (text, func.__name__))
else:
print('%s():' % func.__name__)
return func(*args, **kw)
return wrapper
if callable(text):
return decorator(text)
else:
return decorator
裝飾器用做執(zhí)行時(shí)間統(tǒng)計(jì)
from functools import wrapper
from time import time
def metric(func):
@functools.wraps(func)
def wrapper(*args, **kw):
t0 = time()
func(*args, **kw)
print('%s executed in %s ms' % (func.__name__, (time() - t0) * 1000))
return func
return wrapper
裝飾器用做緩存
def meomo(func):
cache = {}
def wrap(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrap
@meomo
def fibonacci(n):
if n<=1:
return 1
cache = fibonacci(n-1)+fibonacci(n-2)
return cache
"""一個(gè)共有十個(gè)10個(gè)臺(tái)階的樓梯,從下面走到上面,一次只能邁1-3個(gè)臺(tái)階,
并且不能后退,走完這個(gè)樓梯共有多少種方法"""
'''
@meomo
def climb(n,steps):
count = 0
if n == 0:
count +=1
elif n>0:
for step in steps:
count += climb(n-step,steps)
return count
這個(gè)問題比較大,推薦: http://stackoverflow.com/questions/739654/how-can-i-make-a-chain-of-function-decorators-in-python
中文: http://taizilongxu.gitbooks.io/stackoverflow-about-python/content/3/README.html
23 Python中重載
引自知乎:http://www.zhihu.com/question/20053359
函數(shù)重載主要是為了解決兩個(gè)問題。
- 可變參數(shù)類型穴墅。
- 可變參數(shù)個(gè)數(shù)惶室。
另外,一個(gè)基本的設(shè)計(jì)原則是玄货,僅僅當(dāng)兩個(gè)函數(shù)除了參數(shù)類型和參數(shù)個(gè)數(shù)不同以外皇钞,其功能是完全相同的,此時(shí)才使用函數(shù)重載松捉,如果兩個(gè)函數(shù)的功能其實(shí)不同夹界,那么不應(yīng)當(dāng)使用重載,而應(yīng)當(dāng)使用一個(gè)名字不同的函數(shù)隘世。
好吧可柿,那么對(duì)于情況 1 ,函數(shù)功能相同丙者,但是參數(shù)類型不同复斥,python 如何處理?答案是根本不需要處理械媒,因?yàn)?python 可以接受任何類型的參數(shù)目锭,如果函數(shù)的功能相同,那么不同的參數(shù)類型在 python 中很可能是相同的代碼纷捞,沒有必要做成兩個(gè)不同函數(shù)痢虹。
那么對(duì)于情況 2 ,函數(shù)功能相同主儡,但參數(shù)個(gè)數(shù)不同奖唯,python 如何處理?大家知道糜值,答案就是缺省參數(shù)丰捷。對(duì)那些缺少的參數(shù)設(shè)定為缺省參數(shù)即可解決問題。因?yàn)槟慵僭O(shè)函數(shù)功能相同臀玄,那么那些缺少的參數(shù)終歸是需要用的瓢阴。
好了,鑒于情況 1 跟 情況 2 都有了解決方案健无,python 自然就不需要函數(shù)重載了荣恐。
24 __new__
和__init__
的區(qū)別
這個(gè)__new__
確實(shí)很少見到,先做了解吧.
-
__new__
是一個(gè)靜態(tài)方法,而__init__
是一個(gè)實(shí)例方法. -
__new__
方法會(huì)返回一個(gè)創(chuàng)建的實(shí)例,而__init__
什么都不返回. - 只有在
__new__
返回一個(gè)cls的實(shí)例時(shí)后面的__init__
才能被調(diào)用. - 當(dāng)創(chuàng)建一個(gè)新實(shí)例時(shí)調(diào)用
__new__
,初始化一個(gè)實(shí)例時(shí)用__init__
.
ps: __metaclass__
是創(chuàng)建類時(shí)起作用.所以我們可以分別使用__metaclass__
,__new__
和__init__
來分別在類創(chuàng)建,實(shí)例創(chuàng)建和實(shí)例初始化的時(shí)候做一些小手腳.
25 單例模式
? 單例模式是一種常用的軟件設(shè)計(jì)模式。在它的核心結(jié)構(gòu)中只包含一個(gè)被稱為單例類的特殊類。通過單例模式可以保證系統(tǒng)中一個(gè)類只有一個(gè)實(shí)例而且該實(shí)例易于外界訪問叠穆,從而方便對(duì)實(shí)例個(gè)數(shù)的控制并節(jié)約系統(tǒng)資源少漆。如果希望在系統(tǒng)中某個(gè)類的對(duì)象只能存在一個(gè),單例模式是最好的解決方案硼被。
__new__()
在__init__()
之前被調(diào)用示损,用于生成實(shí)例對(duì)象。利用這個(gè)方法和類的屬性的特點(diǎn)可以實(shí)現(xiàn)設(shè)計(jì)模式的單例模式嚷硫。單例模式是指創(chuàng)建唯一對(duì)象检访,單例模式設(shè)計(jì)的類只能實(shí)例
這個(gè)絕對(duì)常考啊.絕對(duì)要記住1~2個(gè)方法,當(dāng)時(shí)面試官是讓手寫的.
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 共享屬性
創(chuàng)建實(shí)例時(shí)把所有實(shí)例的__dict__
指向同一個(gè)字典,這樣它們具有相同的屬性和方法.
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):
instances = {}
def getinstance(*args, **kw):
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()
26 Python中的作用域
Python 中仔掸,一個(gè)變量的作用域總是由在代碼中被賦值的地方所決定的脆贵。
當(dāng) Python 遇到一個(gè)變量的話他會(huì)按照這樣的順序進(jìn)行搜索:
本地作用域(Local)→當(dāng)前作用域被嵌入的本地作用域(Enclosing locals)→全局/模塊作用域(Global)→內(nèi)置作用域(Built-in)
27 GIL線程全局鎖
Python代碼的執(zhí)行由Python 虛擬機(jī)(也叫解釋器主循環(huán),CPython版本)來控制起暮,Python 在設(shè)計(jì)之初就考慮到要在解釋器的主循環(huán)中卖氨,同時(shí)只有一個(gè)線程在執(zhí)行,即在任意時(shí)刻负懦,只有一個(gè)線程在解釋器中運(yùn)行筒捺。對(duì)Python 虛擬機(jī)的訪問由全局解釋器鎖(GIL)來控制,正是這個(gè)鎖能保證同一時(shí)刻只有一個(gè)線程在運(yùn)行纸厉。線程的執(zhí)行速度非常之快系吭,會(huì)讓你誤以為線程是并行執(zhí)行的(并行),但是實(shí)際上都是輪流執(zhí)行(并發(fā)或者串行)颗品。對(duì)于io密集型任務(wù)村斟,python的多線程起到作用,但對(duì)于cpu密集型任務(wù)抛猫,python的多線程幾乎占不到任何優(yōu)勢(shì),還有可能因?yàn)闋?zhēng)奪資源而變慢孩灯。
在多線程環(huán)境中闺金,Python 虛擬機(jī)按以下方式執(zhí)行:
- 設(shè)置GIL
- 切換到一個(gè)線程去運(yùn)行
- 運(yùn)行:
a. 指定數(shù)量的字節(jié)碼指令,或者
b. 線程主動(dòng)讓出控制(可以調(diào)用time.sleep(0)) - 把線程設(shè)置為睡眠狀態(tài)
- 解鎖GIL
- 再次重復(fù)以上所有步驟
在調(diào)用外部代碼(如C/C++擴(kuò)展函數(shù))的時(shí)候峰档,GIL 將會(huì)被鎖定败匹,直到這個(gè)函數(shù)結(jié)束為止(由于在這期間沒有Python 的字節(jié)碼被運(yùn)行,所以不會(huì)做線程切換)讥巡。
join方法 子進(jìn)程結(jié)束切換到父進(jìn)程
多進(jìn)程應(yīng)該避免共享資源掀亩。在多線程中,我們可以比較容易地共享資源欢顷,比如使用全局變量或者傳遞參數(shù)槽棍。在多進(jìn)程情況下,由于每個(gè)進(jìn)程有自己獨(dú)立的內(nèi)存空間,以上方法并不合適炼七。此時(shí)我們可以通過共享內(nèi)存和Manager的方法來共享資源缆巧。但這樣做提高了程序的復(fù)雜度,并因?yàn)橥降男枰档土顺绦虻男省?/li>
解決辦法就是多進(jìn)程和下面的協(xié)程(協(xié)程也只是單CPU,但是能減小切換代價(jià)提升性能).
28 協(xié)程
參考廖雪峰
簡(jiǎn)單點(diǎn)說協(xié)程是進(jìn)程和線程的升級(jí)版,進(jìn)程和線程都面臨著內(nèi)核態(tài)和用戶態(tài)的切換問題而耗費(fèi)許多切換時(shí)間,而協(xié)程就是用戶自己控制切換的時(shí)機(jī),不再需要陷入系統(tǒng)的內(nèi)核態(tài).
Python對(duì)協(xié)程的支持是通過generator實(shí)現(xiàn)的豌拙。
29 閉包
閉包(closure)是函數(shù)式編程的重要的語法結(jié)構(gòu)陕悬。閉包也是一種組織代碼的結(jié)構(gòu),它同樣提高了代碼的可重復(fù)使用性按傅。
當(dāng)一個(gè)內(nèi)嵌函數(shù)引用其外部作作用域的變量,我們就會(huì)得到一個(gè)閉包. 總結(jié)一下,創(chuàng)建一個(gè)閉包必須滿足以下幾點(diǎn):
- 必須有一個(gè)內(nèi)嵌函數(shù)
- 內(nèi)嵌函數(shù)必須引用外部函數(shù)中的變量
- 外部函數(shù)的返回值必須是內(nèi)嵌函數(shù)
感覺閉包還是有難度的,幾句話是說不明白的,還是查查相關(guān)資料.
重點(diǎn)是函數(shù)運(yùn)行后并不會(huì)被撤銷,就像16題的instance字典一樣,當(dāng)函數(shù)運(yùn)行完后,instance并不被銷毀,而是繼續(xù)留在內(nèi)存空間里.這個(gè)功能類似類里的類屬性,只不過遷移到了函數(shù)上.
閉包就像個(gè)空心球一樣,你知道外面和里面,但你不知道中間是什么樣.
30 lambda函數(shù)
其實(shí)就是一個(gè)匿名函數(shù),為什么叫l(wèi)ambda?因?yàn)楹秃竺娴暮瘮?shù)式編程有關(guān).
推薦: 知乎
31 Python函數(shù)式編程
這個(gè)需要適當(dāng)?shù)牧私庖幌掳?畢竟函數(shù)式編程在Python中也做了引用.
推薦: 酷殼
python中函數(shù)式編程支持:
filter 函數(shù)的功能相當(dāng)于過濾器捉超。調(diào)用一個(gè)布爾函數(shù)bool_func
來迭代遍歷每個(gè)seq中的元素;返回一個(gè)使bool_seq
返回值為true的元素的序列唯绍。
>>>a = [1,2,3,4,5,6,7]
>>>b = filter(lambda x: x > 5, a)
>>>print b
>>>[6,7]
map函數(shù)是對(duì)一個(gè)序列的每個(gè)項(xiàng)依次執(zhí)行函數(shù)拼岳,下面是對(duì)一個(gè)序列每個(gè)項(xiàng)都乘以2:
>>> a = map(lambda x:x*2,[1,2,3])
>>> list(a)
[2, 4, 6]
reduce函數(shù)是對(duì)一個(gè)序列的每個(gè)項(xiàng)迭代調(diào)用函數(shù),下面是求3的階乘:
>>> reduce(lambda x,y:x*y,range(1,4))
6
filter函數(shù)用于對(duì)序列的每個(gè)項(xiàng)進(jìn)行迭代推捐,不滿足條件的就會(huì)被踢出序列
>>> filter(lambda x>0:x,range(-10,4))
[1,2,3]
補(bǔ)充:用filter求素?cái)?shù)
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
def _not_divisible(n):
return lambda x: x % n > 0
def primes():
yield 2
it = _odd_iter() # 初始序列
while True:
n = next(it) # 返回序列的第一個(gè)數(shù)
yield n
it = filter(_not_divisible(n), it) # 構(gòu)造新序列
# 打印1000以內(nèi)的素?cái)?shù):
for n in primes():
if n < 1000:
print(n)
else:
break
32 Python里的拷貝
引用和copy(),deepcopy()的區(qū)別
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始對(duì)象
b = a #賦值裂问,傳對(duì)象的引用
c = copy.copy(a) #對(duì)象拷貝,淺拷貝
d = copy.deepcopy(a) #對(duì)象拷貝牛柒,深拷貝
a.append(5) #修改對(duì)象a
a[4].append('c') #修改對(duì)象a中的['a', 'b']數(shù)組對(duì)象
print 'a = ', a
print 'b = ', b
print 'c = ', c
print 'd = ', d
輸出結(jié)果:
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']]
切片的對(duì)象堪簿,切片是淺拷貝還是深拷貝
切片的對(duì)象有l(wèi)ist,tuple,str
“=”,copy,slice屬于淺拷貝
deepcopy就屬于深拷貝
淺拷貝和深拷貝的區(qū)別在于深拷貝是被復(fù)制的對(duì)象作為一個(gè)新的個(gè)體獨(dú)立存在,
任意改變其一不會(huì)對(duì)另一個(gè)對(duì)象造成影響,而淺拷貝不會(huì)產(chǎn)生新的獨(dú)立對(duì)象
33 Python是如何進(jìn)行內(nèi)存管理的
(http://developer.51cto.com/art/201007/213585.html)
答:從三個(gè)方面來說,一對(duì)象的引用計(jì)數(shù)機(jī)制,二垃圾回收機(jī)制,三內(nèi)存池機(jī)制
- 1、對(duì)象的引用計(jì)數(shù)機(jī)制
Python內(nèi)部使用引用計(jì)數(shù)皮壁,來保持追蹤內(nèi)存中的對(duì)象椭更,所有對(duì)象都有引用計(jì)數(shù)。
引用計(jì)數(shù)增加的情況:
1蛾魄,一個(gè)對(duì)象分配一個(gè)新名稱
2虑瀑,將其放入一個(gè)容器中(如列表、元組或字典)
引用計(jì)數(shù)減少的情況:
1滴须,使用del語句對(duì)對(duì)象別名顯示的銷毀
2舌狗,引用超出作用域或被重新賦值
sys.getrefcount( )函數(shù)可以獲得對(duì)象的當(dāng)前引用計(jì)數(shù)
多數(shù)情況下,引用計(jì)數(shù)比你猜測(cè)得要大得多扔水。對(duì)于不可變數(shù)據(jù)(如數(shù)字和字符串)痛侍,解釋器會(huì)在程序的不同部分共享內(nèi)存,以便節(jié)約內(nèi)存魔市。
- 2主届、垃圾回收
1,當(dāng)一個(gè)對(duì)象的引用計(jì)數(shù)歸零時(shí)待德,它將被垃圾收集機(jī)制處理掉君丁。
2,當(dāng)兩個(gè)對(duì)象a和b相互引用時(shí)将宪,del語句可以減少a和b的引用計(jì)數(shù)绘闷,并銷毀用于引用底層對(duì)象的名稱橡庞。然而由于每個(gè)對(duì)象都包含一個(gè)對(duì)其他對(duì)象的應(yīng)用,
因此引用計(jì)數(shù)不會(huì)歸零簸喂,對(duì)象也不會(huì)銷毀毙死。(從而導(dǎo)致內(nèi)存泄露)。為解決這一問題喻鳄,解釋器會(huì)定期執(zhí)行一個(gè)循環(huán)檢測(cè)器扼倘,搜索不可訪問對(duì)象的循環(huán)并刪除它們。
- 3除呵、內(nèi)存池機(jī)制
Python提供了對(duì)內(nèi)存的垃圾收集機(jī)制再菊,但是它將不用的內(nèi)存放到內(nèi)存池而不是返回給操作系統(tǒng)。
1颜曾,Pymalloc機(jī)制纠拔。為了加速Python的執(zhí)行效率,Python引入了一個(gè)內(nèi)存池機(jī)制泛豪,用于管理對(duì)小塊內(nèi)存的申請(qǐng)和釋放稠诲。
2,Python中所有小于256個(gè)字節(jié)的對(duì)象都使用pymalloc實(shí)現(xiàn)的分配器诡曙,而大的對(duì)象則使用系統(tǒng)的malloc臀叙。
3,對(duì)于Python對(duì)象价卤,如整數(shù)劝萤,浮點(diǎn)數(shù)和List,都有其獨(dú)立的私有內(nèi)存池慎璧,對(duì)象間不共享他們的內(nèi)存池床嫌。也就是說如果你分配又釋放了大量的整數(shù),用于緩存這些整數(shù)的內(nèi)存就不能再分配給浮點(diǎn)數(shù)胸私。
34 Python的List和Dict的實(shí)現(xiàn)原理
- 字典按照鍵值對(duì)的形式進(jìn)行存儲(chǔ)厌处,時(shí)間復(fù)雜度為O(1)
- 字典的底層是通過哈希表實(shí)現(xiàn)的,使用開放地址法解決沖突岁疼。所以其查找的時(shí)間復(fù)雜度會(huì)是O(1)嘱蛋,哈希函數(shù)求哈希值
35 Python的is和==
is是對(duì)比地址,==是對(duì)比值
is 比較的是兩個(gè)實(shí)例對(duì)象是不是完全相同,is關(guān)鍵字是查看兩個(gè)對(duì)象是否相同的唯一標(biāo)準(zhǔn),他們是不是同一個(gè)對(duì)象,
占用的內(nèi)存地址是否相同,即比較他們的id
== 比較的是兩個(gè)實(shí)例對(duì)象的內(nèi)容是否相同,即他們的內(nèi)存地址可以不同,默認(rèn)調(diào)用eq方法
切片slice is->False ==->True
序列直接復(fù)制= is->True
大量創(chuàng)建相同內(nèi)容的字符串五续,is->True
小整數(shù)對(duì)象[-5,256]在全局解釋器范圍內(nèi)被放入緩存共重復(fù)使用
a=1 b=1 a is b ->True ==->True
a=257 b=257 a is b ->True ==->True
is運(yùn)算符比==效率高,在變量和None進(jìn)行比較時(shí),應(yīng)該使用is
36 read,readline和readlines
- read 讀取整個(gè)文件
- readline 讀取下一行,使用生成器方法
- readlines 讀取整個(gè)文件到一個(gè)迭代器以供我們遍歷
37 Python2和3的區(qū)別
推薦:Python 2.7.x 與 Python 3.x 的主要差異
補(bǔ)充:Python的編碼問題
python3 bytes和str都可以代表字符序列,前者的實(shí)例包含原始的8位值;bytes.decode('utf-8')
后者的實(shí)例包含unicode字符 str.encode('utf-8')
python2 str和Unicode都可以代表字符序列,與python3不同的是,str的實(shí)例包含原始的8位值,str.decode('utf-8')
而Unicode的實(shí)例則包含unicode字符,unicode.encode(‘utf-8’)
python2 str <--> python3 bytes
python2 unicode <--> python3 str
python2 str.decode(‘utf-8’)–>unicode
unicode.encode(‘utf-8’)–>str
python3 bytes.decode(‘utf-8’)–>str
str.encode(‘utf-8’) –>bytes
數(shù)據(jù)庫
1 事務(wù)
數(shù)據(jù)庫事務(wù)(Database Transaction) ,是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作龄恋,要么完全地執(zhí)行疙驾,要么完全地不執(zhí)行。
徹底理解數(shù)據(jù)庫事務(wù): http://www.hollischuang.com/archives/898
2 數(shù)據(jù)庫索引
推薦: http://tech.meituan.com/mysql-index.html
MySQL索引背后的數(shù)據(jù)結(jié)構(gòu)及算法原理
聚集索引,非聚集索引,B-Tree,B+Tree,最左前綴原理
3 Redis原理
Redis是什么郭毕?
- 是一個(gè)完全開源免費(fèi)的key-value內(nèi)存數(shù)據(jù)庫
- 通常被認(rèn)為是一個(gè)數(shù)據(jù)結(jié)構(gòu)服務(wù)器它碎,主要是因?yàn)槠溆兄S富的數(shù)據(jù)結(jié)構(gòu) strings、map、 list扳肛、sets傻挂、 sorted sets
Redis數(shù)據(jù)庫
? 通常局限點(diǎn)來說,Redis也以消息隊(duì)列的形式存在挖息,作為內(nèi)嵌的List存在金拒,滿足實(shí)時(shí)的高并發(fā)需求。在使用緩存的時(shí)候套腹,redis比memcached具有更多的優(yōu)勢(shì)绪抛,并且支持更多的數(shù)據(jù)類型,把redis當(dāng)作一個(gè)中間存儲(chǔ)系統(tǒng)电禀,用來處理高并發(fā)的數(shù)據(jù)庫操作
- 速度快:使用標(biāo)準(zhǔn)C寫幢码,所有數(shù)據(jù)都在內(nèi)存中完成,讀寫速度分別達(dá)到10萬/20萬
- 持久化:對(duì)數(shù)據(jù)的更新采用Copy-on-write技術(shù)尖飞,可以異步地保存到磁盤上症副,主要有兩種策略,一是根據(jù)時(shí)間政基,更新次數(shù)的快照(save 300 10 )二是基于語句追加方式(Append-only file贞铣,aof)
- 自動(dòng)操作:對(duì)不同數(shù)據(jù)類型的操作都是自動(dòng)的,很安全
- 快速的主--從復(fù)制腋么,官方提供了一個(gè)數(shù)據(jù)咕娄,Slave在21秒即完成了對(duì)Amazon網(wǎng)站10G key set的復(fù)制。
- Sharding技術(shù): 很容易將數(shù)據(jù)分布到多個(gè)Redis實(shí)例中珊擂,數(shù)據(jù)庫的擴(kuò)展是個(gè)永恒的話題圣勒,在關(guān)系型數(shù)據(jù)庫中,主要是以添加硬件摧扇、以分區(qū)為主要技術(shù)形式的縱向擴(kuò)展解決了很多的應(yīng)用場(chǎng)景圣贸,但隨著web2.0、移動(dòng)互聯(lián)網(wǎng)扛稽、云計(jì)算等應(yīng)用的興起吁峻,這種擴(kuò)展模式已經(jīng)不太適合了,所以近年來在张,像采用主從配置用含、數(shù)據(jù)庫復(fù)制形式的,Sharding這種技術(shù)把負(fù)載分布到多個(gè)特理節(jié)點(diǎn)上去的橫向擴(kuò)展方式用處越來越多帮匾。
Redis缺點(diǎn)
- 是數(shù)據(jù)庫容量受到物理內(nèi)存的限制,不能用作海量數(shù)據(jù)的高性能讀寫,因此Redis適合的場(chǎng)景主要局限在較小數(shù)據(jù)量的高性能操作和運(yùn)算上啄骇。
- Redis較難支持在線擴(kuò)容,在集群容量達(dá)到上限時(shí)在線擴(kuò)容會(huì)變得很復(fù)雜瘟斜。為避免這一問題缸夹,運(yùn)維人員在系統(tǒng)上線時(shí)必須確保有足夠的空間痪寻,這對(duì)資源造成了很大的浪費(fèi)。
4 MyISAM和InnoDB
MyISAM 適合于一些需要大量查詢的應(yīng)用虽惭,但其對(duì)于有大量寫操作并不是很好橡类。甚至你只是需要update一個(gè)字段,整個(gè)表都會(huì)被鎖起來芽唇,而別的進(jìn)程顾画,就算是讀進(jìn)程都無法操作直到讀操作完成。另外披摄,MyISAM 對(duì)于 SELECT COUNT(*) 這類的計(jì)算是超快無比的亲雪。
InnoDB 的趨勢(shì)會(huì)是一個(gè)非常復(fù)雜的存儲(chǔ)引擎,對(duì)于一些小的應(yīng)用疚膊,它會(huì)比 MyISAM 還慢义辕。他是它支持“行鎖” ,于是在寫操作比較多的時(shí)候寓盗,會(huì)更優(yōu)秀灌砖。并且,他還支持更多的高級(jí)應(yīng)用傀蚌,比如:事務(wù)基显。
mysql 數(shù)據(jù)庫引擎: http://www.cnblogs.com/0201zcr/p/5296843.html
MySQL存儲(chǔ)引擎--MyISAM與InnoDB區(qū)別: https://segmentfault.com/a/1190000008227211
網(wǎng)絡(luò)
1 三次握手
- 客戶端通過向服務(wù)器端發(fā)送一個(gè)SYN來創(chuàng)建一個(gè)主動(dòng)打開,作為三次握手的一部分善炫×糜模客戶端把這段連接的序號(hào)設(shè)定為隨機(jī)數(shù) A。
- 服務(wù)器端應(yīng)當(dāng)為一個(gè)合法的SYN回送一個(gè)SYN/ACK箩艺。ACK 的確認(rèn)碼應(yīng)為 A+1窜醉,SYN/ACK 包本身又有一個(gè)隨機(jī)序號(hào) B。
- 最后艺谆,客戶端再發(fā)送一個(gè)ACK榨惰。當(dāng)服務(wù)端受到這個(gè)ACK的時(shí)候,就完成了三路握手静汤,并進(jìn)入了連接創(chuàng)建狀態(tài)琅催。此時(shí)包序號(hào)被設(shè)定為收到的確認(rèn)號(hào) A+1,而響應(yīng)則為 B+1虫给。
2 四次揮手
注意: 中斷連接端可以是客戶端藤抡,也可以是服務(wù)器端. 下面僅以客戶端斷開連接舉例, 反之亦然.
- 客戶端發(fā)送一個(gè)數(shù)據(jù)分段, 其中的 FIN 標(biāo)記設(shè)置為1. 客戶端進(jìn)入 FIN-WAIT 狀態(tài). 該狀態(tài)下客戶端只接收數(shù)據(jù), 不再發(fā)送數(shù)據(jù).
- 服務(wù)器接收到帶有 FIN = 1 的數(shù)據(jù)分段, 發(fā)送帶有 ACK = 1 的剩余數(shù)據(jù)分段, 確認(rèn)收到客戶端發(fā)來的 FIN 信息.
- 服務(wù)器等到所有數(shù)據(jù)傳輸結(jié)束, 向客戶端發(fā)送一個(gè)帶有 FIN = 1 的數(shù)據(jù)分段, 并進(jìn)入 CLOSE-WAIT 狀態(tài), 等待客戶端發(fā)來帶有 ACK = 1 的確認(rèn)報(bào)文.
- 客戶端收到服務(wù)器發(fā)來帶有 FIN = 1 的報(bào)文, 返回 ACK = 1 的報(bào)文確認(rèn), 為了防止服務(wù)器端未收到需要重發(fā), 進(jìn)入 TIME-WAIT 狀態(tài). 服務(wù)器接收到報(bào)文后關(guān)閉連接. 客戶端等待 2MSL 后未收到回復(fù), 則認(rèn)為服務(wù)器成功關(guān)閉, 客戶端關(guān)閉連接.
圖解: http://blog.csdn.net/whuslei/article/details/6667471
3 ARP協(xié)議
地址解析協(xié)議(Address Resolution Protocol),其基本功能為透過目標(biāo)設(shè)備的IP地址抹估,查詢目標(biāo)的MAC地址杰捂,以保證通信的順利進(jìn)行。它是IPv4網(wǎng)絡(luò)層必不可少的協(xié)議棋蚌,不過在IPv6中已不再適用嫁佳,并被鄰居發(fā)現(xiàn)協(xié)議(NDP)所替代。
4 urllib和urllib2的區(qū)別
這個(gè)面試官確實(shí)問過,當(dāng)時(shí)答的urllib2可以Post而urllib不可以.
- urllib提供urlencode方法用來GET查詢字符串的產(chǎn)生谷暮,而urllib2沒有蒿往。這是為何urllib常和urllib2一起使用的原因。
- urllib2可以接受一個(gè)Request類的實(shí)例來設(shè)置URL請(qǐng)求的headers湿弦,urllib僅可以接受URL瓤漏。這意味著,你不可以偽裝你的User Agent字符串等颊埃。
5 Post和Get
GET和POST有什么區(qū)別蔬充?及為什么網(wǎng)上的多數(shù)答案都是錯(cuò)的
知乎回答
get: RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1
post: RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1
6 Cookie和Session
Cookie | Session | |
---|---|---|
儲(chǔ)存位置 | 客戶端 | 服務(wù)器端 |
目的 | 跟蹤會(huì)話,也可以保存用戶偏好設(shè)置或者保存用戶名密碼等 | 跟蹤會(huì)話 |
安全性 | 不安全 | 安全 |
session技術(shù)是要使用到cookie的班利,之所以出現(xiàn)session技術(shù)饥漫,主要是為了安全。
7 apache和nginx的區(qū)別
nginx 相對(duì) apache 的優(yōu)點(diǎn):
- 輕量級(jí)罗标,同樣起web 服務(wù)庸队,比apache 占用更少的內(nèi)存及資源
- 抗并發(fā),nginx 處理請(qǐng)求是異步非阻塞的闯割,支持更多的并發(fā)連接彻消,而apache 則是阻塞型的,在高并發(fā)下nginx 能保持低資源低消耗高性能
- 配置簡(jiǎn)潔
- 高度模塊化的設(shè)計(jì)宙拉,編寫模塊相對(duì)簡(jiǎn)單
- 社區(qū)活躍
apache 相對(duì)nginx 的優(yōu)點(diǎn):
- rewrite 宾尚,比nginx 的rewrite 強(qiáng)大
- 模塊超多,基本想到的都可以找到
- 少bug 谢澈,nginx 的bug 相對(duì)較多
- 超穩(wěn)定
8 網(wǎng)站用戶密碼保存
- 明文保存
- 明文hash后保存,如md5
- MD5+Salt方式,這個(gè)salt可以隨機(jī)
- 知乎使用了Bcrypy(好像)加密
9 HTTP和HTTPS
狀態(tài)碼 | 定義 |
---|---|
1xx 報(bào)告 | 接收到請(qǐng)求煌贴,繼續(xù)進(jìn)程 |
2xx 成功 | 步驟成功接收,被理解澳化,并被接受 |
3xx 重定向 | 為了完成請(qǐng)求,必須采取進(jìn)一步措施 |
4xx 客戶端出錯(cuò) | 請(qǐng)求包括錯(cuò)的順序或不能完成 |
5xx 服務(wù)器出錯(cuò) | 服務(wù)器無法完成顯然有效的請(qǐng)求 |
403: Forbidden
404: Not Found
HTTPS握手,對(duì)稱加密,非對(duì)稱加密,TLS/SSL,RSA
10 XSRF和XSS
- CSRF(Cross-site request forgery)跨站請(qǐng)求偽造
- XSS(Cross Site Scripting)跨站腳本攻擊
CSRF重點(diǎn)在請(qǐng)求,XSS重點(diǎn)在腳本
12 RESTful架構(gòu)(SOAP,RPC)
推薦: http://www.ruanyifeng.com/blog/2011/09/restful.html
15 CGI和WSGI
CGI是通用網(wǎng)關(guān)接口崔步,是連接web服務(wù)器和應(yīng)用程序的接口,用戶通過CGI來獲取動(dòng)態(tài)數(shù)據(jù)或文件等缎谷。
CGI程序是一個(gè)獨(dú)立的程序井濒,它可以用幾乎所有語言來寫,包括perl列林,c瑞你,lua,python等等希痴。
WSGI, Web Server Gateway Interface者甲,是Python應(yīng)用程序或框架和Web服務(wù)器之間的一種接口,WSGI的其中一個(gè)目的就是讓用戶可以用統(tǒng)一的語言(Python)編寫前后端砌创。
官方說明:PEP-3333
18 socket
推薦: http://www.360doc.com/content/11/0609/15/5482098_122692444.shtml
Socket=Ip address+ TCP/UDP + port
19 瀏覽器緩存
推薦: http://www.cnblogs.com/skynet/archive/2012/11/28/2792503.html
304 Not Modified
20 HTTP1.0和HTTP1.1
推薦: http://blog.csdn.net/elifefly/article/details/3964766
- 請(qǐng)求頭Host字段,一個(gè)服務(wù)器多個(gè)網(wǎng)站
- 長鏈接
- 文件斷點(diǎn)續(xù)傳
- 身份認(rèn)證,狀態(tài)管理,Cache緩存
HTTP請(qǐng)求8種方法介紹
HTTP/1.1協(xié)議中共定義了8種HTTP請(qǐng)求方法虏缸,HTTP請(qǐng)求方法也被叫做“請(qǐng)求動(dòng)作”鲫懒,不同的方法規(guī)定了不同的操作指定的資源方式。服務(wù)端也會(huì)根據(jù)不同的請(qǐng)求方法做不同的響應(yīng)刽辙。
GET
GET請(qǐng)求會(huì)顯示請(qǐng)求指定的資源窥岩。一般來說GET方法應(yīng)該只用于數(shù)據(jù)的讀取黔夭,而不應(yīng)當(dāng)用于會(huì)產(chǎn)生副作用的非冪等的操作中库菲。
GET會(huì)方法請(qǐng)求指定的頁面信息,并返回響應(yīng)主體剥槐,GET被認(rèn)為是不安全的方法慨灭,因?yàn)镚ET方法會(huì)被網(wǎng)絡(luò)蜘蛛等任意的訪問朦乏。
HEAD
HEAD方法與GET方法一樣,都是向服務(wù)器發(fā)出指定資源的請(qǐng)求氧骤。但是呻疹,服務(wù)器在響應(yīng)HEAD請(qǐng)求時(shí)不會(huì)回傳資源的內(nèi)容部分,即:響應(yīng)主體语淘。這樣诲宇,我們可以不傳輸全部?jī)?nèi)容的情況下,就可以獲取服務(wù)器的響應(yīng)頭信息惶翻。HEAD方法常被用于客戶端查看服務(wù)器的性能姑蓝。
POST
POST請(qǐng)求會(huì) 向指定資源提交數(shù)據(jù),請(qǐng)求服務(wù)器進(jìn)行處理吕粗,如:表單數(shù)據(jù)提交纺荧、文件上傳等,請(qǐng)求數(shù)據(jù)會(huì)被包含在請(qǐng)求體中颅筋。POST方法是非冪等的方法宙暇,因?yàn)檫@個(gè)請(qǐng)求可能會(huì)創(chuàng)建新的資源或/和修改現(xiàn)有資源。
PUT
PUT請(qǐng)求會(huì)身向指定資源位置上傳其最新內(nèi)容议泵,PUT方法是冪等的方法占贫。通過該方法客戶端可以將指定資源的最新數(shù)據(jù)傳送給服務(wù)器取代指定的資源的內(nèi)容。
DELETE
DELETE請(qǐng)求用于請(qǐng)求服務(wù)器刪除所請(qǐng)求URI(統(tǒng)一資源標(biāo)識(shí)符先口,Uniform Resource Identifier)所標(biāo)識(shí)的資源型奥。DELETE請(qǐng)求后指定資源會(huì)被刪除,DELETE方法也是冪等的碉京。
CONNECT
CONNECT方法是HTTP/1.1協(xié)議預(yù)留的厢汹,能夠?qū)⑦B接改為管道方式的代理服務(wù)器。通常用于SSL加密服務(wù)器的鏈接與非加密的HTTP代理服務(wù)器的通信谐宙。
OPTIONS
OPTIONS請(qǐng)求與HEAD類似烫葬,一般也是用于客戶端查看服務(wù)器的性能。 這個(gè)方法會(huì)請(qǐng)求服務(wù)器返回該資源所支持的所有HTTP請(qǐng)求方法,該方法會(huì)用’*’來代替資源名稱搭综,向服務(wù)器發(fā)送OPTIONS請(qǐng)求垢箕,可以測(cè)試服務(wù)器功能是否正常。JavaScript的XMLHttpRequest對(duì)象進(jìn)行CORS跨域資源共享時(shí)兑巾,就是使用OPTIONS方法發(fā)送嗅探請(qǐng)求舰讹,以判斷是否有對(duì)指定資源的訪問權(quán)限。 允許
TRACE
TRACE請(qǐng)求服務(wù)器回顯其收到的請(qǐng)求信息闪朱,該方法主要用于HTTP請(qǐng)求的測(cè)試或診斷。
HTTP/1.1之后增加的方法
在HTTP/1.1標(biāo)準(zhǔn)制定之后钻洒,又陸續(xù)擴(kuò)展了一些方法奋姿。其中使用中較多的是 PATCH 方法:
PATCH
PATCH方法出現(xiàn)的較晚,它在2010年的RFC 5789標(biāo)準(zhǔn)中被定義素标。PATCH請(qǐng)求與PUT請(qǐng)求類似称诗,同樣用于資源的更新。二者有以下兩點(diǎn)不同:
但PATCH一般用于資源的部分更新头遭,而PUT一般用于資源的整體更新寓免。
當(dāng)資源不存在時(shí),PATCH會(huì)創(chuàng)建一個(gè)新的資源计维,而PUT只會(huì)對(duì)已在資源進(jìn)行更新袜香。
編程題
1 列表復(fù)制問題
list1=[None,None]
list2=list1*2 -->[None,None,None,None]
list3=[list1]*2 -->[[None,None],[None,None]]
2 求列表第三大的那個(gè)值
import random
b = [random.randint(1,10000) for i in range(1000)]
max1 = b[0]
max2 = b[1]
max3 = b[2]
for k in b:
if k>max1:
max1,max2,max3 = k,max1,max2
if k>max3 and k<max2:
max3 = k
if k>max2 and k<max1:
max3 = max2
max2 = k
print('{0},{1},{2}'.format(max1,max2,max3))
3 實(shí)現(xiàn)一個(gè)隊(duì)列
# 首先獲取節(jié)點(diǎn),包含next指針和該節(jié)點(diǎn)位置上元素的值
class Node(object):
def __init__(self, val):
self.next = None
self.val = val
class Queue(object):
def __init__(self):
self.first = None
self.last = None
# 進(jìn)隊(duì)操作
def enter(self, n):
# 實(shí)例節(jié)點(diǎn)
n = Node(n)
# 進(jìn)隊(duì)之前先判斷隊(duì)列是否為空鲫惶,即判斷first是否為None
if self.first == None:
# 此時(shí)last==first==n
self.first = n
self.last = self.first
else:
# 將last的指針設(shè)置為n蜈首,值設(shè)置為n
self.last.next = n
self.last = n
# 出隊(duì)
def quit(self):
if self.first == None:
return None
else:
tmp = self.first.val
self.first = self.first.next
return tmp
# 保存隊(duì)列元素到列表
def allQuit(self):
Lists = []
while self.first != None:
Lists.append(self.first.val)
self.first = self.first.next
return Lists
if __name__ == '__main__':
q = Queue()
q.enter(1)
q.enter(2)
q.enter(3)
# print(q.quit())
# print(q.quit())
# print(q.quit())
# print(q.quit())
print(q.allQuit())
4 實(shí)現(xiàn)一個(gè)堆棧
class Stack(object):
def __init__(self):
self.top = None
# 獲取棧頂?shù)闹? def peek(self):
if self.top != None:
return self.top.val
else:
return None
# 入棧操作
def push(self, n):
n = Node(n) # 實(shí)例化節(jié)點(diǎn)
n.next = self.top
self.top = n
return n.val
# 出棧操作
def pop(self):
if self.top == None:
return None
else:
tmp = self.top.val
# return self.top.val
self.top = self.top.next # 棧頂元素下移一位
return tmp
if __name__ == '__main__':
s = Stack()
# s.peek()
s.push(1)
print(s.peek())
s.push(2)
print(s.peek())
s.push(3)
print(s.peek())
print(s.pop())
print(s.pop())
print(s.pop())
print(s.pop())
5 用Python實(shí)現(xiàn)一個(gè)單向鏈表
"""節(jié)點(diǎn)類"""
class Node(object):
def __init__(self, data):
self.data = data
self.nex = None
def __init__(self):
"""初始化鏈表"""
self.head = None
def __len__(self):
pre = self.head
length = 0
while pre:
length += 1
pre = pre.nex
return length
"""追加節(jié)點(diǎn)"""
def append(self, data):
"""
1.head 為none :head-->node
2.tail.nex-->node
:param data:
:return:
"""
node = Node(data)
if self.head is None:
self.head = node
else:
pre = self.head
while pre.nex:
pre = pre.nex
pre.nex = node
# 獲取節(jié)點(diǎn)
def get(self, index):
"""
:param index:
:return:
"""
index = index if index >= 0 else len(self) + index
if len(self) < index or index < 0:
return None
pre = self.head
while index:
pre = pre.nex
index -= 1
return pre
"""設(shè)置節(jié)點(diǎn)"""
def set(self, index, data):
node = self.get(index)
if node:
node.data = data
return node
"""插入節(jié)點(diǎn)"""
def insert(self, index, data):
"""
1.index 插入節(jié)點(diǎn)位置包括正負(fù)數(shù)
2.找到index-1-->pre_node的節(jié)點(diǎn)
3.pre_node.next-->node
node.next-->pre_node.next.next
4.head
:param index:
:param data:
:return:
"""
node = Node(data)
if abs(index + 1) > len(self):
return False
index = index if index >= 0 else len(self) + index + 1
if index == 0:
node.nex = self.head
self.head = node
else:
pre = self.get(index - 1)
if pre:
nex = pre.nex
pre.nex = node
node.nex = nex
else:
return False
return node
"""刪除某個(gè)元素"""
def delete(self, index):
f = index if index > 0 else abs(index + 1)
if len(self) <= f:
return False
pre = self.head
index = index if index >= 0 else len(self) + index
prep = None
while index:
prep = pre
pre = pre.nex
index -= 1
if not prep:
self.head = pre.nex
else:
prep.nex = pre.nex
return pre.data
"""反轉(zhuǎn)鏈表"""
def __reversed__(self):
"""
1.pre-->next 轉(zhuǎn)變?yōu)?next-->pre
2.pre 若是head 則把 pre.nex --> None
3.tail-->self.head
:return:
"""
def reverse(pre_node, node):
if pre_node is self.head:
pre_node.nex = None
if node:
next_node = node.nex
node.nex = pre_node
return reverse(node, next_node)
else:
self.head = pre_node
return reverse(self.head, self.head.nex)
"""清空鏈表"""
def clear(self):
self.head = None
6 用Python實(shí)現(xiàn)一個(gè)雙向鏈表
參考
參考原文 代碼省略
7 臺(tái)階問題/斐波那契
一只青蛙一次可以跳上1級(jí)臺(tái)階,也可以跳上2級(jí)欠母。求該青蛙跳上一個(gè)n級(jí)的臺(tái)階總共有多少種跳法欢策。
fib = lambda n: n if n <= 2 else fib(n - 1) + fib(n - 2)
第二種記憶方法
def memo(func):
cache = {}
def wrap(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrap
@memo
def fib(i):
if i < 2:
return 1
return fib(i-1) + fib(i-2)
第三種方法
def fib(n):
a, b = 0, 1
for _ in xrange(n):
a, b = b, a + b
return b
8 變態(tài)臺(tái)階問題
一只青蛙一次可以跳上1級(jí)臺(tái)階,也可以跳上2級(jí)……它也可以跳上n級(jí)赏淌。求該青蛙跳上一個(gè)n級(jí)的臺(tái)階總共有多少種跳法踩寇。
fib = lambda n: n if n < 2 else 2 * fib(n - 1)
9 去除列表中的重復(fù)元素
用集合
list(set(l))
用字典
l1 = ['b','c','d','b','c','a','a']
l2 = {}.fromkeys(l1).keys()
print l2
用字典并保持順序
l1 = ['b','c','d','b','c','a','a']
l2 = list(set(l1))
l2.sort(key=l1.index)
print l2
列表推導(dǎo)式
l1 = ['b','c','d','b','c','a','a']
l2 = []
[l2.append(i) for i in l1 if not i in l2]
for i in l1:
if i not in l2:
l2.append(i)
sorted排序并且用列表推導(dǎo)式.
l = ['b','c','d','b','c','a','a']
[single.append(i) for i in sorted(l) if i not in single]
print single
10 創(chuàng)建字典的方法
1 直接創(chuàng)建
dict = {'name':'earth', 'port':'80'}
2 工廠方法
items=[('name','earth'),('port','80')]
dict2=dict(items)
dict1=dict((['name','earth'],['port','80']))
3 fromkeys()方法
dict1={}.fromkeys(('x','y'),-1)
dict={'x':-1,'y':-1}
dict2={}.fromkeys(('x','y'))
dict2={'x':None, 'y':None}
11 合并兩個(gè)有序列表
知乎遠(yuǎn)程面試要求編程
尾遞歸
def _recursion_merge_sort2(l1, l2, tmp):
if len(l1) == 0 or len(l2) == 0:
tmp.extend(l1)
tmp.extend(l2)
return tmp
else:
if l1[0] < l2[0]:
tmp.append(l1[0])
del l1[0]
else:
tmp.append(l2[0])
del l2[0]
return _recursion_merge_sort2(l1, l2, tmp)
def recursion_merge_sort2(l1, l2):
return _recursion_merge_sort2(l1, l2, [])
循環(huán)算法
思路:
定義一個(gè)新的空列表
比較兩個(gè)列表的首個(gè)元素
小的就插入到新列表里
把已經(jīng)插入新列表的元素從舊列表刪除
直到兩個(gè)舊列表有一個(gè)為空
再把舊列表加到新列表后面
def loop_merge_sort(l1, l2):
tmp = []
while len(l1) > 0 and len(l2) > 0:
if l1[0] < l2[0]:
tmp.append(l1[0])
del l1[0]
else:
tmp.append(l2[0])
del l2[0]
tmp.extend(l1)
tmp.extend(l2)
return tmp
pop彈出
a = [1,2,3,7]
b = [3,4,5]
def merge_sortedlist(a,b):
c = []
while a and b:
if a[0] >= b[0]:
c.append(b.pop(0))
else:
c.append(a.pop(0))
while a:
c.append(a.pop(0))
while b:
c.append(b.pop(0))
return c
print merge_sortedlist(a,b)
12 歸并排序
def merge(a, b):
c = []
h = j = 0
# 依次便利,拿到兩個(gè)數(shù)組更小的元素六水,
while j < len(a) and h < len(b):
# 如果0索引位置的元素a更小俺孙,添加a[0]到c,再將a[1]與b[0]比較缩擂,依次類推鼠冕,剩余最后的元素就是兩個(gè)數(shù)組的最大值
if a[j] < b[h]:
c.append(a[j])
j += 1
else:
c.append(b[h])
h += 1
if j == len(a):
for i in b[h:]:
c.append(i)
else:
for i in a[j:]:
c.append(i)
return c
def merge_sort(lists):
if len(lists) <= 1:
return lists
middle = len(lists)//2
left = merge_sort(lists[:middle])
right = merge_sort(lists[middle:])
return merge(left, right)
if __name__ == '__main__':
a = [4, 7, 8, 3, 5, 9,10]
print(merge_sort(a))
13 質(zhì)數(shù)和日期問題
class PrimeNumbers(object):
def __init__(self, start, end):
self.start = start
self.end = end
def isPrimeNumber(self, k):
if k < 2:
return False
for i in range(2, k):
if k % i == 0:
return False
return True
def __iter__(self):
for k in range(self.start, self.end + 1):
if self.isPrimeNumber(k):
yield k
#print(isinstance(PrimeNumbers(1,100)))
if __name__ == '__main__':
a = PrimeNumbers(1, 100)
f = a.__iter__()
L = []
for i in f:
L.append(i)
print(L)
# 寫一個(gè)函數(shù),計(jì)算給定日期是該年的第幾天和周數(shù)
def count(year,month,day):
count=0
if (year%4==0 and year%100!=0) or year%400==0:
print('%d年是閏年胯盯,2月份有29天懈费!'%year)
list1=[31,29,31,30,31,30,31,31,30,31,30,31]
for i in range(month-1):
count=count+list1[i]
return count+
else:
print('%d年是平年,2月份有29天博脑!' % year)
li2 = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
for i in range(month-1):
count +=li2[i]
return count+day
if __name__ == "__main__":
year = int(input('請(qǐng)輸入年份:'))
month = int(input('請(qǐng)輸入月份:'))
day = int(input('請(qǐng)輸入日期:'))
count = count(year,month,day)
print('%d年%d月%d日是今年的第%d天憎乙!'%(year,month,day,count))
14 二分查找
#coding:utf-8
def binary_search(list,item):
low = 0
high = len(list)-1
while low<=high:
mid = (low+high)/2
guess = list[mid]
if guess>item:
high = mid-1
elif guess<item:
low = mid+1
else:
return mid
return None
mylist = [1,3,5,7,9]
print binary_search(mylist,3)
參考: http://blog.csdn.net/u013205877/article/details/76411718
15 打印文件夾
def print_directory_contents(sPath):
"""
這個(gè)函數(shù)接受文件夾的名稱作為輸入?yún)?shù)票罐,
返回該文件夾中文件的路徑,
以及其包含文件夾中文件的路徑泞边。
"""
import os
for sChild in os.listdir(sPath):
sChildPath = os.path.join(sPath,sChild)
if os.path.isdir(sChildPath):
print_directory_contents(sChildPath)
else:
print sChildPath
16 找零問題
#coding:utf-8
#values是硬幣的面值values = [ 25, 21, 10, 5, 1]
#valuesCounts 錢幣對(duì)應(yīng)的種類數(shù)
#money 找出來的總錢數(shù)
#coinsUsed 對(duì)應(yīng)于目前錢幣總數(shù)i所使用的硬幣數(shù)目
def coinChange(values,valuesCounts,money,coinsUsed):
#遍歷出從1到money所有的錢數(shù)可能
for cents in range(1,money+1):
minCoins = cents
#把所有的硬幣面值遍歷出來和錢數(shù)做對(duì)比
for kind in range(0,valuesCounts):
if (values[kind] <= cents):
temp = coinsUsed[cents - values[kind]] +1
if (temp < minCoins):
minCoins = temp
coinsUsed[cents] = minCoins
print ('面值:{0}的最少硬幣使用數(shù)為:{1}'.format(cents, coinsUsed[cents]))
思路: http://blog.csdn.net/wdxin1322/article/details/9501163
方法: http://www.cnblogs.com/ChenxofHit/archive/2011/03/18/1988431.html
17 二叉樹節(jié)點(diǎn)
class Node(object):
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
tree = Node(1, Node(3, Node(7, Node(0)), Node(6)), Node(2, Node(5), Node(4)))
17 前中后序遍歷
深度遍歷改變順序就OK了
#coding:utf-8
#二叉樹的遍歷
#簡(jiǎn)單的二叉樹節(jié)點(diǎn)類
class Node(object):
def __init__(self,value,left,right):
self.value = value
self.left = left
self.right = right
#中序遍歷:遍歷左子樹,訪問當(dāng)前節(jié)點(diǎn),遍歷右子樹
def mid_travelsal(root):
if root.left is None:
mid_travelsal(root.left)
#訪問當(dāng)前節(jié)點(diǎn)
print(root.value)
if root.right is not None:
mid_travelsal(root.right)
#前序遍歷:訪問當(dāng)前節(jié)點(diǎn),遍歷左子樹,遍歷右子樹
def pre_travelsal(root):
print (root.value)
if root.left is not None:
pre_travelsal(root.left)
if root.right is not None:
pre_travelsal(root.right)
#后續(xù)遍歷:遍歷左子樹,遍歷右子樹,訪問當(dāng)前節(jié)點(diǎn)
def post_trvelsal(root):
if root.left is not None:
post_trvelsal(root.left)
if root.right is not None:
post_trvelsal(root.right)
print (root.value)
18 求最大樹深
def maxDepth(root):
if not root:
return 0
return max(maxDepth(root.left), maxDepth(root.right)) + 1
19 求兩棵樹是否相同
def isSameTree(p, q):
if p == None and q == None:
return True
elif p and q :
return p.val == q.val and isSameTree(p.left,q.left) and isSameTree(p.right,q.right)
else :
return False
20 前序中序求后序
推薦: http://blog.csdn.net/hinyunsin/article/details/6315502
def rebuild(pre, center):
if not pre:
return
cur = Node(pre[0])
index = center.index(pre[0])
cur.left = rebuild(pre[1:index + 1], center[:index])
cur.right = rebuild(pre[index + 1:], center[index + 1:])
return cur
def deep(root):
if not root:
return
deep(root.left)
deep(root.right)
print root.data
21 廣度遍歷和深度遍歷二叉樹
給定一個(gè)數(shù)組该押,構(gòu)建二叉樹,并且按層次打印這個(gè)二叉樹
22 快排
#coding:utf-8
def quicksort(list):
if len(list)<2:
return list
else:
midpivot = list[0]
lessbeforemidpivot = [i for i in list[1:] if i<=midpivot]
biggerafterpivot = [i for i in list[1:] if i > midpivot]
finallylist = quicksort(lessbeforemidpivot)+[midpivot]+quicksort(biggerafterpivot)
return finallylist
print quicksort([2,4,6,7,1,2,5])
# 使用lambda函數(shù)實(shí)現(xiàn)
quicksort=lambda data:data if len(data)<2 else quicksort([item for item in data[1:] if item<=data[0]])+[data[0]]+quicksort([item for item in data[1:] if item>data[0]])
print quicksort([2,4,6,7,1,2,5])
23 層次遍歷
def lookup(root):
row = [root]
while row:
print(row)
row = [kid for item in row for kid in (item.left, item.right) if kid]
24 深度遍歷
def deep(root):
if not root:
return
print root.data
deep(root.left)
deep(root.right)
if __name__ == '__main__':
lookup(tree)
deep(tree)