參考原文:https://github.com/taizilongxu/interview_python
Python的函數(shù)傳遞
- 傳入的參數(shù)都是值的引用地址
- 值分為2類,可變的與不可變的
- 可變的有
list,dict。不可變的有string,tuple,numbers - 可變的可以修改,但不能改引用
- 不可變的不能修改,賦值操作等于改引用
@staticmethod 和 @classmethod 和實(shí)例方法
- Python有3個(gè)對象方法,靜態(tài)方法,類方法和實(shí)例方法。
- 靜態(tài)方法staticmethod,類和實(shí)例都可以用。一般用于與函數(shù)數(shù)據(jù)無關(guān),純處理,工具類函數(shù)
- 類方法,傳遞的參數(shù)是cls(類本身)。
- 實(shí)例方法,類不可調(diào)用,傳遞的參數(shù)self是實(shí)例。
類變量和實(shí)例變量
類變量與實(shí)例變量與參數(shù)的機(jī)制相同。
# Part 1
class Person:
name="aaa"
p1=Person()
p2=Person()
p1.name="bbb"
print p1.name # bbb
print p2.name # aaa
print Person.name # aaa
# Part 2
class Person:
name=[]
p1=Person()
p2=Person()
p1.name.append(1)
print p1.name # [1]
print p2.name # [1]
print Person.name # [1]
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ū)別其他用戶自定義的命名,以防沖突.
_foo:
一種約定,用來指定變量私有.程序員用來指定私有變量的一種方式.
__foo:
這個(gè)有真正的意義:解析器用_classname__foo來代替這個(gè)名字,以區(qū)別和其他類相同的命名。
以雙下劃線做前綴的名稱(特別是方法名)并不是一種慣例;它對解釋器有特定含義。Python會(huì)改寫這些名稱,以免與子類中定義的名稱產(chǎn)生沖突。
迭代器與生成器與yield
生成器
要理解Yield你必須先理解當(dāng)你調(diào)用函數(shù)的時(shí)候,函數(shù)里的代碼并沒有運(yùn)行.函數(shù)僅僅返回生成器對象,這就是它最微妙的地方:-)
然后呢,每當(dāng)for語句迭代生成器的時(shí)候你的代碼才會(huì)運(yùn)轉(zhuǎn).
現(xiàn)在,到了最難的部分:
當(dāng)for語句第一次調(diào)用函數(shù)里返回的生成器對象,函數(shù)里的代碼就開始運(yùn)作,直到碰到y(tǒng)ield,然后會(huì)返回本次循環(huán)的第一個(gè)返回值.所以下一次調(diào)用也將運(yùn)行一次循環(huán)然后返回下一個(gè)值,直到?jīng)]有值可以返回.
一旦函數(shù)運(yùn)行并沒有碰到y(tǒng)eild語句就認(rèn)為生成器已經(jīng)為空了.原因有可能是循環(huán)結(jié)束或者沒有滿足if/else之類的.
返回一次數(shù)據(jù)后便結(jié)束,等待下一次調(diào)用,返回的方法就是用yield
用途
便于大數(shù)據(jù)的生成,不會(huì)占用大量內(nèi)存。
迭代器
L = [1,2,3,4]
i = iter(L)
i.next()
裝飾器
基礎(chǔ)
- Python中函數(shù)都是對象
- 所有變量都是引用
- 函數(shù)也是引用
實(shí)踐與說明
可以傳入函數(shù),也可以返回函數(shù)
# 定義一個(gè)可接受參數(shù)的裝飾器
from functools import wraps
import logging
def logged(level, name=None, message=None):
def decorate(func):
logname = name if name else func.__module__
log = logging.getLogger(logname)
logmsg = message if message else func.__name__
@wraps(func)
def wrapper(*args, **kwargs):
log.log(level, logmsg)
return func(*args, **kwargs)
return wrapper
return decorate
@logged(logging.DEBUG, 'debug')
def add(x, y):
return x + y
"""
等于=>
def add(x, y):
return x + y
add = looged(logging.DEBUG, 'debug')(add)
"""
其他
- 原函數(shù)被裝飾器操作后,會(huì)丟失原來的函數(shù)元數(shù)據(jù)。
- @wraps 裝飾器就是解決上述問題的。
new和init的區(qū)別
- 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.
單例模式
GIL線程全局鎖
線程全局鎖(Global Interpreter Lock),即Python為了保證線程安全而采取的獨(dú)立線程運(yùn)行的限制,說白了就是一個(gè)核只能在同一時(shí)間運(yùn)行一個(gè)線程.
見Python 最難的問題
解決辦法就是多進(jìn)程和下面的協(xié)程(協(xié)程也只是單CPU,但是能減小切換代價(jià)提升性能).
Python的List
推薦: http://www.itdecent.cn/p/J4U6rR
Python的is
is是對比地址,==是對比值
read,readline和readlines
read 讀取整個(gè)文件
readline 讀取下一行,使用生成器方法
readlines 讀取整個(gè)文件到一個(gè)迭代器以供我們遍歷