一、函數(shù)
函數(shù)的作用:可以計(jì)算出一個(gè)返回值,最大化代碼重用,最小化代碼冗余,流程的分解。
1、函數(shù)相關(guān)的語句和表達(dá)式
語句 例子
Calls myfunc(‘diege','eggs',meat=‘lit’) #使用函數(shù)
def,return,yield def adder(a,b=1,*c):
return a+b+c[0]
global changer():
global x;x='new'
lambda Funcs=[lambad x:x**2,lambad x:x*3]
2、編寫函數(shù)
def創(chuàng)建了一個(gè)對(duì)象并將其賦值給某一個(gè)變量名。
return將一個(gè)結(jié)果對(duì)象發(fā)送給調(diào)用者。
函數(shù)是通過賦值(對(duì)象引用)傳遞的。
參數(shù)通過賦值傳遞給函數(shù)。
global聲明了一個(gè)模塊級(jí)的變量并被賦值。
參數(shù),返回值以及變量并不是聲明
def <name>(arg1,age2,...,agrN):
<statements>
return <value
函數(shù)主體往往都包含了一個(gè)return語句(不是必須的),如果它沒有出現(xiàn),那么函數(shù)將會(huì)在控制流執(zhí)行完函數(shù)主體時(shí)結(jié)束,技術(shù)上,沒有返回值的函數(shù)自動(dòng)返回了none對(duì)象。
return可以在函數(shù)主體中的任何地方出現(xiàn)。它表示函數(shù)調(diào)用的結(jié)束,并將結(jié)果返回至函數(shù)調(diào)用。
不要嘗試判斷傳入?yún)?shù)的對(duì)象類型,這樣實(shí)質(zhì)上破壞了函數(shù)的靈活性,把函數(shù)限制在特定的類型上
3、作用域
作用域:變量定義以及查找的地方。
本地變量:在函數(shù)內(nèi)定義的變量為本地變量。
全局變量:在文件內(nèi)[模塊內(nèi)]函數(shù)外定義的變量為全局變量
Python創(chuàng)建,改變或者查找變量名都是在所謂的命名空間(一個(gè)保存變量名的地方,模塊中為__main__)中進(jìn)行。作用域這個(gè)術(shù)語指的就是命名空間。
也就說,在代碼中變量名被賦值的位置決定了這個(gè)變量名能被訪問到的范圍
一個(gè)函數(shù)所有變量名都與函數(shù)的命名空間相關(guān)聯(lián)。
*def內(nèi)定義變量名def內(nèi)使用,是本地變量
*def之中的變量名與def之外的變量名不發(fā)生沖突,使用別處相同的變量名也沒問題。
函數(shù)定義了本地作用域,而模塊定義了全局作用域。兩作用域關(guān)系。
*內(nèi)嵌的模塊是全局作用域:對(duì)于外部的全局變量就成為了一個(gè)模塊對(duì)象的屬性
*全局作用域的作用范圍僅限單個(gè)文件:不要被全局迷惑,這里的全局是一個(gè)文件的頂層的變量名,僅對(duì)這個(gè)文件內(nèi)部的代碼而言是全局。
Python中,沒有一個(gè)無所不包的情景文件作用域。替代的方法是,變量名由模塊文件隔開,必須精準(zhǔn)地導(dǎo)入一個(gè)模塊文件才能夠使用這文件中
定義的變量名,
*每次對(duì)函數(shù)的調(diào)用都創(chuàng)建了一個(gè)新的本地作用域。
*賦值的變量名廢除聲明為全局變量,否則均為本地變量。
*所用的變量名都可以歸納為本地,全局,或者內(nèi)置。(內(nèi)置:ptyhon預(yù)定義的__builtin__模塊提供的)
變量名解析:LEGB原則
對(duì)一個(gè)def語句
*變量名引用分為三個(gè)作用域進(jìn)行查找:首先查找本地,然后是函數(shù)內(nèi)(如果有),之后全局,最后內(nèi)置。
*默認(rèn)情況下,變量名賦值會(huì)創(chuàng)建或改變本地變量
*全局聲明將賦值變量名映射到模塊文件內(nèi)部的作用域。
global
global語句包含關(guān)鍵字global
*全局變量是位于模塊文件內(nèi)部頂層的變量名
*全局變量如果是在函數(shù)內(nèi)部被賦值的話,并需經(jīng)過聲明
*全局變量名在函數(shù)的內(nèi)部不經(jīng)過聲明也可以被引用
4、傳遞參數(shù)
參數(shù)傳遞:傳遞給函數(shù)作為其輸入對(duì)象的方式
*參數(shù)的傳遞是通過自動(dòng)將對(duì)象賦值給本地變量來實(shí)現(xiàn)的。
*在函數(shù)內(nèi)部的參數(shù)名的賦值不會(huì)影響調(diào)用者。
*改變函數(shù)的可變對(duì)象參數(shù)的值也許會(huì)對(duì)調(diào)用者有影響。
換句話說,因?yàn)閰?shù)是簡單的通過賦值進(jìn)行對(duì)象的傳遞,函數(shù)能夠改變傳入的可變對(duì)象,因此其結(jié)果會(huì)影響調(diào)用者。
*不可變參數(shù)是“通過值”進(jìn)行傳遞。
像整數(shù)和字符串這樣的對(duì)象是通過對(duì)象引用而不是拷貝進(jìn)行傳遞的,但是因?yàn)槟銦o論如何都不可能在原處改變不可變對(duì)象,實(shí)際的效果就是很像創(chuàng)建了一份拷貝。
可變對(duì)象是通過“指針”進(jìn)行傳遞的。
避免可變參數(shù)的修改
在Python中,默認(rèn)通過引用(也就是指針)進(jìn)行函數(shù)的參數(shù)傳遞。如果不想在函數(shù)內(nèi)部在原處的修改影響傳遞給它的對(duì)象。那么,能夠簡單的創(chuàng)建一個(gè)可變對(duì)象的拷貝。
我們總是能夠在調(diào)用時(shí)對(duì)列表進(jìn)行拷貝
L=[1,2]
changer(X,L[:])
如果不想改變傳入的對(duì)象,無論函數(shù)是如何調(diào)用的,我們可以在函數(shù)內(nèi)部進(jìn)行拷貝,避免可變參數(shù)的修改
>>> def changer(a,b):
... a=2
... b=b[:]
... b[0]='diege'
特定參數(shù)匹配模型
參數(shù)在ptyhon中總是通過賦值進(jìn)行傳遞,傳入的對(duì)象賦值給了在def頭部的變量名。盡管這樣,在模型的上層,python提供了額外的工具,該工具改變了調(diào)用過中
賦值時(shí)參數(shù)對(duì)象匹配在頭部的參數(shù)名的優(yōu)先級(jí)。這些工具是可選的。
總結(jié)與特定模式有關(guān)的語法:
語法 位置 解釋
func(value) 調(diào)用者 常規(guī)參數(shù),通過位置進(jìn)行匹配,從左到右進(jìn)行匹配
func(name=value) 調(diào)用者 關(guān)鍵字參數(shù),通過變量名匹配
func(*name) 調(diào)用者 以name傳遞所有的對(duì)象,并作為獨(dú)立的基于位置的參數(shù)
func(**name) 調(diào)用者 以name成對(duì)的傳遞所有的關(guān)鍵字/值,并作為獨(dú)立的關(guān)鍵字的參數(shù)
def func(name) 函數(shù) 常規(guī)參數(shù):通過位置或變量名進(jìn)行匹配
def func(name=value) 函數(shù) 默認(rèn)參數(shù)值:如果沒有在調(diào)用中傳遞的話,就是用默認(rèn)值
def func(*name) 函數(shù) 匹配并收集(在元組中)所有包含位置的參數(shù)
def func(**name) 函數(shù) 匹配并收集(在字典中)所有包含位置的參數(shù)。
5、匿名函數(shù):lamdba
lambad 創(chuàng)建了一個(gè)之后能夠被調(diào)用的函數(shù),它返回了一個(gè)函數(shù)而不是將這個(gè)函數(shù)賦值給一個(gè)變量名。
lambda表達(dá)式
lanbda arg1,arg2,...,argN:expression using arguments
lambda 是一個(gè)表達(dá)式,而不是一個(gè)語句
lambda的主體是一個(gè)單個(gè)的表達(dá)式,而不是代碼塊
func(x,y,z):return x+y+z
默認(rèn)參數(shù)也能夠再lambda參數(shù)中使用,就像在def中使用一樣。
lambda a='free',b='file',c='feel':a+b+c
6、作參數(shù)來應(yīng)用函數(shù)
內(nèi)置函數(shù)apply
當(dāng)需要變得更加動(dòng)態(tài)的話,可以通過將一個(gè)函數(shù)作為一個(gè)參數(shù)傳遞給apply來調(diào)用一個(gè)生成的函數(shù),并且
也將傳給那個(gè)函數(shù)的參數(shù)作為一個(gè)元組傳遞給apply函數(shù)()
apply(函數(shù),參數(shù)1(元組),參數(shù)2(元組))
7、在序列中映射函數(shù):map
使用內(nèi)置工具map,map函數(shù)會(huì)對(duì)一個(gè)序列對(duì)象中的每一個(gè)元素應(yīng)用被傳入的函數(shù),并且返回一個(gè)包含了所有函數(shù)調(diào)用結(jié)果的一個(gè)列表。
map(函數(shù),傳入函數(shù)的序列對(duì)象)
>>> def inc(x):return x+10
>>> L=[1,2,3,4,5]
>>> map(inc,L)
[11, 12, 13, 14, 15]
>>> L=[1,2,3,4,5]
map嵌套lambda
>>> map((lambda x:x+3),L)
[4, 5, 6, 7, 8]
高級(jí)功能:提供了多個(gè)序列作為參數(shù),它能夠并行返回分別以每個(gè)序列的元素作為【函數(shù)對(duì)應(yīng)參數(shù)】得到的結(jié)果的列表
>>> pow(3,4)
81
>>> map(pow,[1,2,3],[2,3,4]) #1**2,2**3,3**4
[1, 8, 81]
8、函數(shù)式編程工具:filter和reduce
函數(shù)式編程的意思就是對(duì)序列應(yīng)用一些函數(shù)的工具。
基于某一測試函數(shù)過濾出一些元素-filter
對(duì)每對(duì)元素都應(yīng)用函數(shù)并運(yùn)行到最后結(jié)果-reduce
>>> filter((lambda x:x>0),range(-5,5))
[1, 2, 3, 4]
這個(gè)等效于for range:if語句
reduce稍微復(fù)雜一點(diǎn)。這里兩個(gè)reduce調(diào)用,計(jì)算在一個(gè)列表中所有元素加起來和以及乘起來的乘積
>>> reduce((lambda x,y:x+y),[1,2,3,4])
10
>>> reduce((lambda x,y:x*y),[1,2,3,4])
24
依次計(jì)算
9、重訪列表解析:映射
1)、列表解析基礎(chǔ)
>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> map((lambda x:x**2),range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
2)、增加測試和嵌套循環(huán)
在for之后編寫if分支,用來增加邏輯選擇,if分支相當(dāng)filter
>>> [x for x in range(5) if x%2==0]
[0, 2, 4]
>>> filter((lambda x:x%2==0),range(5))
[0, 2, 4]
3)filter出來的列表可以作為map的第2個(gè)參數(shù)
>>> map((lambda x:x**2),filter((lambda x:x%2==0),range(5)))
[0, 4, 16]
列表解析和map的對(duì)比
兩者類似,都會(huì)收集對(duì)序列或其他可迭代對(duì)象中每個(gè)元素應(yīng)用元算后的結(jié)果(一次一個(gè)項(xiàng)目),從而創(chuàng)建新列表。其主要差異在于。
map會(huì)對(duì)每個(gè)元素應(yīng)用函數(shù),而列表解析則是應(yīng)用任意的表達(dá)式。因此,列表解析更通用一些,可以像map那樣應(yīng)用函數(shù)調(diào)用表達(dá)式,
但是,map需要一個(gè)函數(shù)才能應(yīng)用其他種類的表達(dá)式(函數(shù)是map的第一參數(shù)).列表解析也支持?jǐn)U展語法,如果,嵌套for循環(huán)和if
分句從而可以包含內(nèi)置函數(shù)filter的功能。
10、重返迭代器:生成器
編寫的函數(shù)能夠返回一個(gè)值,并且稍后還可以從它剛才離開的地方仍然返回值。這樣的函數(shù)被認(rèn)作是生成器,因?yàn)樗鼈冸S時(shí)間生成一個(gè)序列的值。
大多數(shù)方面生成器函數(shù)就像一般函數(shù),在Python它們被自動(dòng)用作實(shí)現(xiàn)迭代協(xié)議,因它只能夠再迭代的語境中出現(xiàn)。
生成器和一般的函數(shù)之間代碼上最大的不同就是一個(gè)生成器yield一個(gè)值,而不是return一個(gè)值。yield語句將會(huì)將函數(shù)關(guān)起,并向它的調(diào)用者返回一個(gè)值
但是保存足夠的狀態(tài)信息為了讓其能夠在函數(shù)從它掛起的地方恢復(fù)。
包含yield的語句的函數(shù)將會(huì)特地編譯成為生成器。當(dāng)調(diào)用它時(shí),他們返回一個(gè)生成器對(duì)象,這個(gè)生成器對(duì)象支持迭代器對(duì)象接口。
>>> def Dtest(N):
... for i in range(N):
... yield i**2
使用
>>> for i in Dtest(5):
... print i,':',
...
0 : 1 : 4 : 9 : 16 :
查看過程
>>> x=Dtest(4)
>>> x.next()
0
>>> x.next()
11、函數(shù)設(shè)計(jì)概念
*耦合性:對(duì)于輸入使用參數(shù),并且對(duì)于輸出使用return語句
*耦合性:只有在真正必要的情況下使用全局變量。
*耦合性:不要改變可變類型的參數(shù),除非調(diào)用者希望這樣做。
*聚合性:每一個(gè)函數(shù)都應(yīng)該有一個(gè)單一的,同一的目標(biāo)
*大?。好恳粋€(gè)函數(shù)應(yīng)該相對(duì)較小。
*耦合:避免直接改變?cè)诹硪粋€(gè)模塊文件中的變量。
函數(shù)是對(duì)象:簡潔調(diào)用
二、模塊
1、基本
每個(gè)文件都是一個(gè)模塊,并且模塊導(dǎo)入其他模塊之后就可以使用導(dǎo)入模塊定義的變量名。模塊可以由兩個(gè)語句和一個(gè)重要的內(nèi)置函數(shù)進(jìn)行處理。
import: 使客戶端(導(dǎo)入者)以一個(gè)整體獲取一個(gè)模塊。
from:容許客戶端從一個(gè)模塊文件中獲取特定的變量名。
reload:在不中止Python程序的情況下,提供了一個(gè)重新載入模塊文件代碼的方法。
import和from是賦值語句,是可執(zhí)行的語句,可以嵌套到if ,def語句中和def一樣import和from都是隱性賦值語句
在一個(gè)模塊文件的頂層定義的所有變量名都成為了被導(dǎo)入的模塊對(duì)象的屬性。
模塊至少有三個(gè)角色:
代碼重用:模塊還是定義變量名的空間,被認(rèn)作是屬性??梢员欢鄠€(gè)外部的客戶端應(yīng)用。
系統(tǒng)命名空間的劃分:
現(xiàn)實(shí)共享服務(wù)和數(shù)據(jù):
2、python程序構(gòu)架
import如何工作
執(zhí)行三個(gè)步驟
1)、找到模塊文件
2)、編譯成位碼(需要時(shí))
3)、執(zhí)行模塊的代碼來創(chuàng)建其所定義的對(duì)象。
在之后導(dǎo)入相同的模塊時(shí)候,會(huì)跳過這三個(gè)步驟,而只提取內(nèi)存中已加載模塊對(duì)象。
搜索模塊
導(dǎo)入模塊時(shí),不帶模塊的后綴名,比如.py
Python搜索模塊的路徑:
1)、程序的主目錄
2)、PTYHONPATH目錄(如果已經(jīng)進(jìn)行了設(shè)置)
3)、標(biāo)準(zhǔn)連接庫目錄(一般在/usr/local/lib/python2.X/)
4)、任何的.pth文件的內(nèi)容(如果存在的話).新功能,允許用戶把有效果的目錄添加到模塊搜索路徑中去
.pth后綴的文本文件中一行一行的地列出目錄。
這四個(gè)組建組合起來就變成了sys.path了,
>>> import sys
>>> sys.path
導(dǎo)入時(shí),Python會(huì)自動(dòng)由左到右搜索這個(gè)列表中每個(gè)目錄。
第1,第3元素是自動(dòng)定義的,第2,第4可以用于擴(kuò)展路徑,從而包括自己的源碼目錄。
3、模塊的創(chuàng)建和使用。
創(chuàng)建模塊
后綴.py文本文件,模塊頂層指定的所有變量名都會(huì)變成其屬性。
定義一個(gè)module.py模塊
name='diege'
age=18
def printer(x):
print x
使用模塊
import全部導(dǎo)入,import將整個(gè)模塊對(duì)象賦值給一個(gè)變量名,模塊只導(dǎo)入一次,因?yàn)樵摬僮鏖_銷大
>>> import module
屬性
>>> module.name
'diege'
函數(shù)
>>> module.printer('hi')
hi
from語句:from 將獲?。◤?fù)制)模塊特定變量名
from會(huì)把變量名賦值到另一個(gè)作用域,所以它就可以讓我們直接在腳本中使用復(fù)制后的變量名,而不是通過模塊
from 模塊名 import 需要復(fù)制的屬性 將一個(gè)或多個(gè)變量名賦值給另一個(gè)模塊中同名的對(duì)象
from 模塊名 import 需要復(fù)制的屬性 as 新的屬性名 將一個(gè)或者多個(gè)變量名賦值給另一個(gè)模塊中不同名的對(duì)象
from * 語句 from 模塊名 import * 取得模塊頂層所有賦了值的變量名的拷貝
>>> from module import name
>>> name
'diege
>>> from module import name as myname
>>> myname
'diege'
>>> from module import printer as PR
>>> PR('hi python')
hi python
>>> from module import name,age 復(fù)制多個(gè)變量名時(shí)要用逗號(hào)隔開
>>> name,age
('diege', 18)
>>> from module import name as myname,age as myage 復(fù)制多個(gè)變量名并改變需時(shí)需要用逗號(hào)隔開多個(gè)as
>>> from module import *
4、模塊命名空間
模塊最好理解為變量名的封裝,簡而言之,模塊就是命名空間(變量名建立所在的場所),而存在于模塊之內(nèi)的變量名就是模塊對(duì)象的屬性。
文件生成命名空間
*模塊語句會(huì)在首次導(dǎo)入時(shí)執(zhí)行。
*頂層的賦值語句會(huì)創(chuàng)建模塊屬性(文件頂層不在的def和class之內(nèi)的,但def和class隱性創(chuàng)建的變量名也屬于模塊屬性)。賦值的變量名會(huì)存儲(chǔ)在模塊的命名空間內(nèi)。
*模塊的命名空間能通過屬性__dict__(module.__dict__)或dir(module)獲取
由于導(dǎo)入而建立的模塊的命名空間是字典,可通過模塊對(duì)象相關(guān)聯(lián)的內(nèi)置__dict__屬性讀取。
dir函數(shù)查看,大至與對(duì)象的__dict__屬性的鍵排序后的列表相等,但是它還包含了類繼承的變量名。
*模塊是一個(gè)獨(dú)立的作用域。
5、重載模塊
模塊程序代碼默認(rèn)值對(duì)每個(gè)過程執(zhí)行一次,要強(qiáng)制使模塊代碼重新載入并重新運(yùn)算需要使用reload內(nèi)置函數(shù)。
reload是函數(shù),import是語句。兩個(gè)語法不一樣。
>>> import module
>>> reload(module)
<module 'module' from 'module.pyc'>
>>> reload(test17)
<module 'test17' from '/root/test17.py'>
reload()之前需得import過一次
6、模塊包
除模塊名以外,導(dǎo)入也可以指定目錄路徑,Pytyh代碼的目錄就是稱為包。因此這類導(dǎo)入就稱為包導(dǎo)入
import dir1.dir2.mod
from dir1.dir2.mod import x
.號(hào)路徑相當(dāng)于機(jī)器上目錄層次的路徑。
dir1在容器目錄dir0中,dir0這個(gè)目錄可以在Python模塊搜索路徑中找到。
__init__.py包文件
如果選擇使用包導(dǎo)入,那就必須遵循一條約束:包導(dǎo)入語句的路徑的每個(gè)目錄內(nèi)部都必須有__init__.py這個(gè)文件,
否則導(dǎo)入包會(huì)失敗。
dir1和dir2中必須包含__init__.py,容器目錄dir0不需要這類文件。因?yàn)楸旧頉]有列在import語句中
__init__.py文件可以包含程序代碼,也可以是空的。 更通常情況下,__init__.py文件扮演了包初始化的掛鉤
替目錄產(chǎn)生模塊命名空間以及用目錄導(dǎo)入實(shí)現(xiàn)from *行為的角色。
*包初始化:
首次導(dǎo)入某個(gè)目錄時(shí),會(huì)自動(dòng)執(zhí)行該目錄下__init__.py文件中所有程序代碼。
所以這個(gè)文件就是放置包內(nèi)文件所需初始化的代碼的場所??梢允褂闷涑跏蓟募瑒?chuàng)建所需的數(shù)據(jù)文件,
連接數(shù)據(jù)庫等。
*模塊命名空間的初始化:
*from * 語句的行為:
作為一個(gè)高級(jí)功能,可以在__init__.py文件中使用__all__列表來定義目錄以form *語句形式導(dǎo)入時(shí),需要
導(dǎo)出什么。__all__列表是指出當(dāng)包(目錄—)名稱使用from *的時(shí)候,應(yīng)該導(dǎo)入的子模塊名稱清單。
eg:
/usr/local/lib/python2.7/sqlite3/__init__.py
from dbapi2 import *
/usr/local/lib/python2.7/site-packages/mod_python/__init__.py
__all__ = ["apache", "cgihandler", "psp",
"publisher", "util", "python22"]
version = "3.3.1"
常見的第三方擴(kuò)展都是以包目錄形式發(fā)布給用戶,而不是單純的模塊列表。
這樣就可以通過路徑來導(dǎo)入
7、在模塊中隱藏?cái)?shù)據(jù)
最小化from *的破壞:_X和__all__達(dá)到隱藏變量名的目的
有種特定情況,可以把下劃線放在變量名前(_X),可以防止客戶端使用from * 語句導(dǎo)入模塊名時(shí),把其中的那些變量名賦值出去。這其實(shí)是為了把命名空間的破壞最小化而已。下劃線和__all__不是私有聲明,還可以通過其他導(dǎo)入形式修改這類變量名。例如import語句、from module import _X
以外,也可以在模塊頂層把變量名的字符串列表賦值給變量__all__,以達(dá)到類似于_X命名慣例的隱藏效果【__all__是不隱藏的】
mod_python.__all__ 可以看到可以用from *語句復(fù)制那些變量名
_X和__all__ 對(duì)比
_X 隱藏了 無法from *
__all__ 只顯示,from *只能獲取__all__中指定的,其他隱藏。
python中from *會(huì)先尋找模塊內(nèi)的__all__列表,有的話復(fù)制其中的變量名,如果沒有定義的話,from *就會(huì)復(fù)制開頭沒有下劃線的所有命令名。
怎么覺得__all__列表里存放的是模塊呢???
8、混合用法模式:__name__和__main__
這是一個(gè)特殊的與模塊相關(guān)的技巧,可以把文件作為模塊導(dǎo)入,并以獨(dú)立式程序的形式運(yùn)行。每個(gè)模塊都有個(gè)名為__name__的內(nèi)置屬性。Python會(huì)自動(dòng)設(shè)置該屬性:
*如果文件是以頂層程序文件執(zhí)行,在啟動(dòng)時(shí),__name__就會(huì)被設(shè)置為字符串__main__
*如果文件被導(dǎo)入,__name__就會(huì)改設(shè)成客戶端所了解模塊名。
結(jié)果就是模塊可以檢測自己的__name__,來確定它是執(zhí)行還是在導(dǎo)入。
定義一個(gè)文件test15.py
def tester():
print "It's python test!"
if __name__=='__main__':
tester()
9、修改模塊搜索路徑
可以通過PYTHONPATH以及可能的.pth路徑文件進(jìn)行定制。
Python程序本身是修改sys.path的內(nèi)置列表。sys.path在程序啟動(dòng)時(shí)就進(jìn)行初始化,但那之后也可以隨意對(duì)其元素進(jìn)行刪除,附加和重設(shè)
>>> import sys
>>> sys.path
# cd /tmp/
# python
>>> sys.path.append('/root')【增加新的路徑】
>>> sys.path
['', '/usr/local/lib/python2.7/site-packages/MySQL_python-1.2.3-py2.7-freebsd-8.2-RELEASE-i386.egg', '/usr/local/lib/python2.7/site-packages/setuptools-0.6c12dev_r88846-py2.7.egg', '/usr/local/lib/python2.7/site-packages/Babel-0.9.6-py2.7.egg', '/usr/local/lib/python2.7/site-packages/Trac-0.12.3-py2.7.egg', '/usr/local/lib/python2.7/site-packages/Genshi-0.6-py2.7.egg', '/usr/local/lib/python2.7/site-packages/IniAdmin-0.2_r10454-py2.7.egg', '/usr/local/lib/python2.7/site-packages/TracAccountManager-0.4dev_r11251-py2.7.egg', '/usr/local/lib/python2.7/site-packages/SvnAuthzAdminPlugin-0.2-py2.7.egg', '/usr/local/lib/python27.zip', '/usr/local/lib/python2.7', '/usr/local/lib/python2.7/plat-freebsd8', '/usr/local/lib/python2.7/lib-tk', '/usr/local/lib/python2.7/lib-old', '/usr/local/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/site-packages', '/root']
導(dǎo)入/root目錄下test17.py,注意啟動(dòng)python時(shí)在/tmp目錄,所以/root不是程序啟動(dòng)目錄
>>> import test17
>>> dir(test17)
>>> test17.lessthan(3,4)
True
10、相對(duì)導(dǎo)入語法
from語句現(xiàn)在可以使用點(diǎn)號(hào)(.)更傾向于同一個(gè)包內(nèi)的模塊(稱為包相對(duì)導(dǎo)入),而不是位于模塊導(dǎo)入搜索路徑上其他地方的模塊(所謂的絕對(duì)導(dǎo)入)
*現(xiàn)在,可以使用點(diǎn)號(hào)指出該導(dǎo)入應(yīng)該與其所在包相關(guān)聯(lián):這類導(dǎo)入傾向于導(dǎo)入位于該包內(nèi)的模塊,而不是導(dǎo)入搜索路徑sys.path上其他地方的同名模塊
from .apache CallBack as CB
同一個(gè)包內(nèi)導(dǎo)入apache模塊CallBack為CB變量
11、模塊設(shè)計(jì)理念
*總是在Python的模塊內(nèi)編寫代碼
*模塊耦合要降到最底:全局變量。模塊應(yīng)該盡可能和其他模塊的全局變量無關(guān)。
*最大化模塊的沾合性:統(tǒng)一目標(biāo)
*模塊應(yīng)該少去修改其他模塊的的變量。
模塊是對(duì)象:元程序
模塊通過內(nèi)置屬性顯示了他們大多數(shù)的特性。因此,可很容易的編寫程序來管理其他程序。我們通常稱這類管理程序?yàn)樵绦?,因?yàn)樗麄兪窃谄渌到y(tǒng)上工作。這也稱為內(nèi)省,因?yàn)槌绦蚰芸匆姾吞幚韺?duì)象的內(nèi)部。內(nèi)省是高級(jí)功能,但是它可以做創(chuàng)建程序工具,取得模塊內(nèi)名為name的屬性,方法包括
(1)可以使用結(jié)合點(diǎn)號(hào)運(yùn)算,
(2)或者對(duì)模塊的屬性字典進(jìn)行索引運(yùn)算(在內(nèi)置__dict__屬性中顯示)。
(3)Python也在sys.modules字典中導(dǎo)出所有已經(jīng)加載的模塊。
(4)并提供一個(gè)內(nèi)置函數(shù)getattrr,讓我們以字符串名來取出屬性。(就好像object.attr,而attr是運(yùn)行時(shí)的字符串)
>>> test17.name
'diege'
>>> test17.__dict__.keys()
>>> test17.__dict__['name']
'diege
>>> test17.__dict__['lessthan']
<function lessthan at 0x28495844>
>>> sys.modules 顯示所有加載的模塊
>>> sys.modules['test17']
<module 'test17' from '/root/test17.py'>
>>> sys.modules['test17'].name
'diege
>>> getattr(test17,'lessthan')
<function lessthan at 0x28495bc4>
12、模塊陷阱
1)頂層代碼的語句次序的重要性
*在導(dǎo)入時(shí),模塊文件頂層的程序代碼(不在函數(shù)內(nèi))一旦python運(yùn)行,就會(huì)立刻執(zhí)行。因此,該語句是無法引用文件后面位置賦值的變量名。
*位于函數(shù)主體內(nèi)的代碼知道函數(shù)被調(diào)用后才會(huì)運(yùn)行。
作為一條原則,如果需要把立即執(zhí)行的代碼和def一起混用,就要把def放在文件前面,把頂層代碼放在后面。這樣的話,你的函數(shù)在使用的代碼運(yùn)行時(shí),可以保證他們都已定義并賦值過了。
2)通過變量名字符串導(dǎo)入模塊的方法
import或from語句內(nèi)的模塊名是”硬編碼“的變量名。
>>> x='string'
>>> import x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named x
這里python會(huì)試著導(dǎo)入文件x.py
為了避免發(fā)生這樣的問題,通常的做法就是把import語句構(gòu)造成python代碼的字符串,再傳給exec語句執(zhí)行:
>>> modname='string'
>>> exec "import "+modname
exec語句以及和他類似eval會(huì)編譯一段字符串代碼,將其傳給Python解析器來執(zhí)行。
3)from復(fù)制變量名,而不是連接
from語句其實(shí)是在導(dǎo)入者的作用域內(nèi)對(duì)變量名的賦值語句,也就是變量名拷貝運(yùn)算,而不是變量名的別名機(jī)制。它的實(shí)現(xiàn)和python所有賦值運(yùn)算都一樣,微妙之處在于,共享對(duì)象的代碼存在于不同的文件中。然后,我們使用import獲得了整個(gè)模塊,然后賦值某個(gè)點(diǎn)號(hào)運(yùn)算的變量名,就會(huì)修改導(dǎo)入的模塊中的變量名。點(diǎn)號(hào)運(yùn)算把python定向到了模塊對(duì)象,而不是賦值模塊中對(duì)象。
4)from*會(huì)讓變量語義模糊
5)reload不會(huì)影響from導(dǎo)入
6)不要使用reload、from以及交互模式測試
reload中引用模塊得通過import至少將其加載一次:
不要from導(dǎo)入之后reload
7) reload使用沒有傳遞性
當(dāng)重載一個(gè)模塊時(shí),Python只會(huì)重載那個(gè)模塊的文件,不會(huì)自動(dòng)重載該文件重載嘶碰巧還要導(dǎo)入的模塊。
8)遞歸形式的from import無法工作
不要在遞歸導(dǎo)入中使用 from。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。