日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Python學(xué)習(xí)筆記總結(jié)(二):函數(shù)和模塊

 浸心閣 2015-03-26
一、函數(shù)
函數(shù)的作用:可以計算出一個返回值,最大化代碼重用,最小化代碼冗余,流程的分解。
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)建了一個對象并將其賦值給某一個變量名。
return將一個結(jié)果對象發(fā)送給調(diào)用者。
函數(shù)是通過賦值(對象引用)傳遞的。
參數(shù)通過賦值傳遞給函數(shù)。
global聲明了一個模塊級的變量并被賦值。
參數(shù),返回值以及變量并不是聲明
def <name>(arg1,age2,...,agrN):
    <statements>
     return <value
函數(shù)主體往往都包含了一個return語句(不是必須的),如果它沒有出現(xiàn),那么函數(shù)將會在控制流執(zhí)行完函數(shù)主體時結(jié)束,技術(shù)上,沒有返回值的函數(shù)自動返回了none對象。
return可以在函數(shù)主體中的任何地方出現(xiàn)。它表示函數(shù)調(diào)用的結(jié)束,并將結(jié)果返回至函數(shù)調(diào)用。

不要嘗試判斷傳入?yún)?shù)的對象類型,這樣實質(zhì)上破壞了函數(shù)的靈活性,把函數(shù)限制在特定的類型上
3、作用域
作用域:變量定義以及查找的地方。
本地變量:在函數(shù)內(nèi)定義的變量為本地變量。
全局變量:在文件內(nèi)[模塊內(nèi)]函數(shù)外定義的變量為全局變量
Python創(chuàng)建,改變或者查找變量名都是在所謂的命名空間(一個保存變量名的地方,模塊中為__main__)中進(jìn)行。作用域這個術(shù)語指的就是命名空間。
也就說,在代碼中變量名被賦值的位置決定了這個變量名能被訪問到的范圍
一個函數(shù)所有變量名都與函數(shù)的命名空間相關(guān)聯(lián)。
*def內(nèi)定義變量名def內(nèi)使用,是本地變量
*def之中的變量名與def之外的變量名不發(fā)生沖突,使用別處相同的變量名也沒問題。
函數(shù)定義了本地作用域,而模塊定義了全局作用域。兩作用域關(guān)系。
*內(nèi)嵌的模塊是全局作用域:對于外部的全局變量就成為了一個模塊對象的屬性
*全局作用域的作用范圍僅限單個文件:不要被全局迷惑,這里的全局是一個文件的頂層的變量名,僅對這個文件內(nèi)部的代碼而言是全局。
Python中,沒有一個無所不包的情景文件作用域。替代的方法是,變量名由模塊文件隔開,必須精準(zhǔn)地導(dǎo)入一個模塊文件才能夠使用這文件中
定義的變量名,
*每次對函數(shù)的調(diào)用都創(chuàng)建了一個新的本地作用域。
*賦值的變量名廢除聲明為全局變量,否則均為本地變量。
*所用的變量名都可以歸納為本地,全局,或者內(nèi)置。(內(nèi)置:ptyhon預(yù)定義的__builtin__模塊提供的)

變量名解析:LEGB原則
對一個def語句
*變量名引用分為三個作用域進(jìn)行查找:首先查找本地,然后是函數(shù)內(nèi)(如果有),之后全局,最后內(nèi)置。
*默認(rèn)情況下,變量名賦值會創(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ù)作為其輸入對象的方式
*參數(shù)的傳遞是通過自動將對象賦值給本地變量來實現(xiàn)的。
*在函數(shù)內(nèi)部的參數(shù)名的賦值不會影響調(diào)用者。
*改變函數(shù)的可變對象參數(shù)的值也許會對調(diào)用者有影響。
換句話說,因為參數(shù)是簡單的通過賦值進(jìn)行對象的傳遞,函數(shù)能夠改變傳入的可變對象,因此其結(jié)果會影響調(diào)用者。
*不可變參數(shù)是“通過值”進(jìn)行傳遞。
像整數(shù)和字符串這樣的對象是通過對象引用而不是拷貝進(jìn)行傳遞的,但是因為你無論如何都不可能在原處改變不可變對象,實際的效果就是很像創(chuàng)建了一份拷貝。
可變對象是通過“指針”進(jìn)行傳遞的。

避免可變參數(shù)的修改
在Python中,默認(rèn)通過引用(也就是指針)進(jìn)行函數(shù)的參數(shù)傳遞。如果不想在函數(shù)內(nèi)部在原處的修改影響傳遞給它的對象。那么,能夠簡單的創(chuàng)建一個可變對象的拷貝。
我們總是能夠在調(diào)用時對列表進(jìn)行拷貝
L=[1,2]
changer(X,L[:])
如果不想改變傳入的對象,無論函數(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)行傳遞,傳入的對象賦值給了在def頭部的變量名。盡管這樣,在模型的上層,python提供了額外的工具,該工具改變了調(diào)用過中
賦值時參數(shù)對象匹配在頭部的參數(shù)名的優(yōu)先級。這些工具是可選的。

總結(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傳遞所有的對象,并作為獨立的基于位置的參數(shù)
func(**name)        調(diào)用者    以name成對的傳遞所有的關(guān)鍵字/值,并作為獨立的關(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)建了一個之后能夠被調(diào)用的函數(shù),它返回了一個函數(shù)而不是將這個函數(shù)賦值給一個變量名。
lambda表達(dá)式
lanbda arg1,arg2,...,argN:expression using arguments
lambda 是一個表達(dá)式,而不是一個語句
lambda的主體是一個單個的表達(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)需要變得更加動態(tài)的話,可以通過將一個函數(shù)作為一個參數(shù)傳遞給apply來調(diào)用一個生成的函數(shù),并且
也將傳給那個函數(shù)的參數(shù)作為一個元組傳遞給apply函數(shù)()
apply(函數(shù),參數(shù)1(元組),參數(shù)2(元組))

7、在序列中映射函數(shù):map
使用內(nèi)置工具map,map函數(shù)會對一個序列對象中的每一個元素應(yīng)用被傳入的函數(shù),并且返回一個包含了所有函數(shù)調(diào)用結(jié)果的一個列表。
map(函數(shù),傳入函數(shù)的序列對象)
>>> 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]
高級功能:提供了多個序列作為參數(shù),它能夠并行返回分別以每個序列的元素作為【函數(shù)對應(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ù)式編程的意思就是對序列應(yīng)用一些函數(shù)的工具。
基于某一測試函數(shù)過濾出一些元素-filter
對每對元素都應(yīng)用函數(shù)并運行到最后結(jié)果-reduce
>>> filter((lambda x:x>0),range(-5,5))
[1, 2, 3, 4]
這個等效于for range:if語句
reduce稍微復(fù)雜一點。這里兩個reduce調(diào)用,計算在一個列表中所有元素加起來和以及乘起來的乘積
>>> reduce((lambda x,y:x+y),[1,2,3,4])
10
>>> reduce((lambda x,y:x*y),[1,2,3,4])
24
依次計算

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個參數(shù)
>>> map((lambda x:x**2),filter((lambda x:x%2==0),range(5)))
[0, 4, 16]
列表解析和map的對比
兩者類似,都會收集對序列或其他可迭代對象中每個元素應(yīng)用元算后的結(jié)果(一次一個項目),從而創(chuàng)建新列表。其主要差異在于。
map會對每個元素應(yīng)用函數(shù),而列表解析則是應(yīng)用任意的表達(dá)式。因此,列表解析更通用一些,可以像map那樣應(yīng)用函數(shù)調(diào)用表達(dá)式,
但是,map需要一個函數(shù)才能應(yīng)用其他種類的表達(dá)式(函數(shù)是map的第一參數(shù)).列表解析也支持?jǐn)U展語法,如果,嵌套for循環(huán)和if
分句從而可以包含內(nèi)置函數(shù)filter的功能。

10、重返迭代器:生成器
編寫的函數(shù)能夠返回一個值,并且稍后還可以從它剛才離開的地方仍然返回值。這樣的函數(shù)被認(rèn)作是生成器,因為它們隨時間生成一個序列的值。
大多數(shù)方面生成器函數(shù)就像一般函數(shù),在Python它們被自動用作實現(xiàn)迭代協(xié)議,因它只能夠再迭代的語境中出現(xiàn)。
生成器和一般的函數(shù)之間代碼上最大的不同就是一個生成器yield一個值,而不是return一個值。yield語句將會將函數(shù)關(guān)起,并向它的調(diào)用者返回一個值
但是保存足夠的狀態(tài)信息為了讓其能夠在函數(shù)從它掛起的地方恢復(fù)。
包含yield的語句的函數(shù)將會特地編譯成為生成器。當(dāng)調(diào)用它時,他們返回一個生成器對象,這個生成器對象支持迭代器對象接口。
>>> 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è)計概念
*耦合性:對于輸入使用參數(shù),并且對于輸出使用return語句
*耦合性:只有在真正必要的情況下使用全局變量。
*耦合性:不要改變可變類型的參數(shù),除非調(diào)用者希望這樣做。
*聚合性:每一個函數(shù)都應(yīng)該有一個單一的,同一的目標(biāo)
*大小:每一個函數(shù)應(yīng)該相對較小。
*耦合:避免直接改變在另一個模塊文件中的變量。
函數(shù)是對象:簡潔調(diào)用


二、模塊
1、基本
每個文件都是一個模塊,并且模塊導(dǎo)入其他模塊之后就可以使用導(dǎo)入模塊定義的變量名。模塊可以由兩個語句和一個重要的內(nèi)置函數(shù)進(jìn)行處理。
import: 使客戶端(導(dǎo)入者)以一個整體獲取一個模塊。
from:容許客戶端從一個模塊文件中獲取特定的變量名。
reload:在不中止Python程序的情況下,提供了一個重新載入模塊文件代碼的方法。
import和from是賦值語句,是可執(zhí)行的語句,可以嵌套到if ,def語句中和def一樣import和from都是隱性賦值語句

在一個模塊文件的頂層定義的所有變量名都成為了被導(dǎo)入的模塊對象的屬性。
模塊至少有三個角色:
代碼重用:模塊還是定義變量名的空間,被認(rèn)作是屬性??梢员欢鄠€外部的客戶端應(yīng)用。
系統(tǒng)命名空間的劃分:
現(xiàn)實共享服務(wù)和數(shù)據(jù):

2、python程序構(gòu)架
import如何工作
執(zhí)行三個步驟
1)、找到模塊文件
2)、編譯成位碼(需要時)
3)、執(zhí)行模塊的代碼來創(chuàng)建其所定義的對象。
在之后導(dǎo)入相同的模塊時候,會跳過這三個步驟,而只提取內(nèi)存中已加載模塊對象。
搜索模塊
導(dǎo)入模塊時,不帶模塊的后綴名,比如.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后綴的文本文件中一行一行的地列出目錄。
這四個組建組合起來就變成了sys.path了,
>>> import sys
>>> sys.path
導(dǎo)入時,Python會自動由左到右搜索這個列表中每個目錄。
第1,第3元素是自動定義的,第2,第4可以用于擴(kuò)展路徑,從而包括自己的源碼目錄。

3、模塊的創(chuàng)建和使用。
創(chuàng)建模塊
后綴.py文本文件,模塊頂層指定的所有變量名都會變成其屬性。
定義一個module.py模塊
name='diege'
age=18
def printer(x):
        print x
使用模塊
import全部導(dǎo)入,import將整個模塊對象賦值給一個變量名,模塊只導(dǎo)入一次,因為該操作開銷大
>>> import module
屬性
>>> module.name
'diege'
函數(shù)
>>> module.printer('hi')
hi
from語句:from 將獲?。◤?fù)制)模塊特定變量名
from會把變量名賦值到另一個作用域,所以它就可以讓我們直接在腳本中使用復(fù)制后的變量名,而不是通過模塊
from 模塊名 import 需要復(fù)制的屬性 將一個或多個變量名賦值給另一個模塊中同名的對象
from 模塊名 import 需要復(fù)制的屬性 as 新的屬性名 將一個或者多個變量名賦值給另一個模塊中不同名的對象
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ù)制多個變量名時要用逗號隔開
>>> name,age
('diege', 18)
>>> from module import name as myname,age as myage  復(fù)制多個變量名并改變需時需要用逗號隔開多個as
>>> from module import *

4、模塊命名空間
模塊最好理解為變量名的封裝,簡而言之,模塊就是命名空間(變量名建立所在的場所),而存在于模塊之內(nèi)的變量名就是模塊對象的屬性。
文件生成命名空間
*模塊語句會在首次導(dǎo)入時執(zhí)行。
*頂層的賦值語句會創(chuàng)建模塊屬性(文件頂層不在的def和class之內(nèi)的,但def和class隱性創(chuàng)建的變量名也屬于模塊屬性)。賦值的變量名會存儲在模塊的命名空間內(nèi)。
*模塊的命名空間能通過屬性__dict__(module.__dict__)或dir(module)獲取
由于導(dǎo)入而建立的模塊的命名空間是字典,可通過模塊對象相關(guān)聯(lián)的內(nèi)置__dict__屬性讀取。
dir函數(shù)查看,大至與對象的__dict__屬性的鍵排序后的列表相等,但是它還包含了類繼承的變量名。
*模塊是一個獨立的作用域。

5、重載模塊
模塊程序代碼默認(rèn)值對每個過程執(zhí)行一次,要強(qiáng)制使模塊代碼重新載入并重新運算需要使用reload內(nèi)置函數(shù)。
reload是函數(shù),import是語句。兩個語法不一樣。
>>> 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
.號路徑相當(dāng)于機(jī)器上目錄層次的路徑。
dir1在容器目錄dir0中,dir0這個目錄可以在Python模塊搜索路徑中找到。
__init__.py包文件
如果選擇使用包導(dǎo)入,那就必須遵循一條約束:包導(dǎo)入語句的路徑的每個目錄內(nèi)部都必須有__init__.py這個文件,
否則導(dǎo)入包會失敗。
dir1和dir2中必須包含__init__.py,容器目錄dir0不需要這類文件。因為本身沒有列在import語句中
__init__.py文件可以包含程序代碼,也可以是空的。 更通常情況下,__init__.py文件扮演了包初始化的掛鉤
替目錄產(chǎn)生模塊命名空間以及用目錄導(dǎo)入實現(xiàn)from *行為的角色。
*包初始化:
首次導(dǎo)入某個目錄時,會自動執(zhí)行該目錄下__init__.py文件中所有程序代碼。
所以這個文件就是放置包內(nèi)文件所需初始化的代碼的場所??梢允褂闷涑跏蓟募?,創(chuàng)建所需的數(shù)據(jù)文件,
連接數(shù)據(jù)庫等。
*模塊命名空間的初始化:
*from * 語句的行為:
作為一個高級功能,可以在__init__.py文件中使用__all__列表來定義目錄以form *語句形式導(dǎo)入時,需要
導(dǎo)出什么。__all__列表是指出當(dāng)包(目錄—)名稱使用from *的時候,應(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、在模塊中隱藏數(shù)據(jù)
最小化from *的破壞:_X和__all__達(dá)到隱藏變量名的目的
有種特定情況,可以把下劃線放在變量名前(_X),可以防止客戶端使用from * 語句導(dǎo)入模塊名時,把其中的那些變量名賦值出去。這其實是為了把命名空間的破壞最小化而已。下劃線和__all__不是私有聲明,還可以通過其他導(dǎo)入形式修改這類變量名。例如import語句、from module import _X
以外,也可以在模塊頂層把變量名的字符串列表賦值給變量__all__,以達(dá)到類似于_X命名慣例的隱藏效果【__all__是不隱藏的】
mod_python.__all__ 可以看到可以用from *語句復(fù)制那些變量名
_X和__all__ 對比
_X 隱藏了 無法from *
__all__  只顯示,from *只能獲取__all__中指定的,其他隱藏。
python中from *會先尋找模塊內(nèi)的__all__列表,有的話復(fù)制其中的變量名,如果沒有定義的話,from *就會復(fù)制開頭沒有下劃線的所有命令名。
怎么覺得__all__列表里存放的是模塊呢???

8、混合用法模式:__name__和__main__
這是一個特殊的與模塊相關(guān)的技巧,可以把文件作為模塊導(dǎo)入,并以獨立式程序的形式運行。每個模塊都有個名為__name__的內(nèi)置屬性。Python會自動設(shè)置該屬性:
*如果文件是以頂層程序文件執(zhí)行,在啟動時,__name__就會被設(shè)置為字符串__main__
*如果文件被導(dǎo)入,__name__就會改設(shè)成客戶端所了解模塊名。
結(jié)果就是模塊可以檢測自己的__name__,來確定它是執(zhí)行還是在導(dǎo)入。
定義一個文件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在程序啟動時就進(jìn)行初始化,但那之后也可以隨意對其元素進(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,注意啟動python時在/tmp目錄,所以/root不是程序啟動目錄
>>> import test17 
>>> dir(test17)
>>> test17.lessthan(3,4)
True

10、相對導(dǎo)入語法
from語句現(xiàn)在可以使用點號(.)更傾向于同一個包內(nèi)的模塊(稱為包相對導(dǎo)入),而不是位于模塊導(dǎo)入搜索路徑上其他地方的模塊(所謂的絕對導(dǎo)入)
*現(xiàn)在,可以使用點號指出該導(dǎo)入應(yīng)該與其所在包相關(guān)聯(lián):這類導(dǎo)入傾向于導(dǎo)入位于該包內(nèi)的模塊,而不是導(dǎo)入搜索路徑sys.path上其他地方的同名模塊
from .apache CallBack as CB
同一個包內(nèi)導(dǎo)入apache模塊CallBack為CB變量

11、模塊設(shè)計理念
*總是在Python的模塊內(nèi)編寫代碼
*模塊耦合要降到最底:全局變量。模塊應(yīng)該盡可能和其他模塊的全局變量無關(guān)。
*最大化模塊的沾合性:統(tǒng)一目標(biāo)
*模塊應(yīng)該少去修改其他模塊的的變量。
模塊是對象:元程序
模塊通過內(nèi)置屬性顯示了他們大多數(shù)的特性。因此,可很容易的編寫程序來管理其他程序。我們通常稱這類管理程序為元程序,因為他們是在其他系統(tǒng)上工作。這也稱為內(nèi)省,因為程序能看見和處理對象的內(nèi)部。內(nèi)省是高級功能,但是它可以做創(chuàng)建程序工具,取得模塊內(nèi)名為name的屬性,方法包括
(1)可以使用結(jié)合點號運算,
(2)或者對模塊的屬性字典進(jìn)行索引運算(在內(nèi)置__dict__屬性中顯示)。
(3)Python也在sys.modules字典中導(dǎo)出所有已經(jīng)加載的模塊。
(4)并提供一個內(nèi)置函數(shù)getattrr,讓我們以字符串名來取出屬性。(就好像object.attr,而attr是運行時的字符串)
>>> 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ù)內(nèi))一旦python運行,就會立刻執(zhí)行。因此,該語句是無法引用文件后面位置賦值的變量名。
*位于函數(shù)主體內(nèi)的代碼知道函數(shù)被調(diào)用后才會運行。
作為一條原則,如果需要把立即執(zhí)行的代碼和def一起混用,就要把def放在文件前面,把頂層代碼放在后面。這樣的話,你的函數(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會試著導(dǎo)入文件x.py
為了避免發(fā)生這樣的問題,通常的做法就是把import語句構(gòu)造成python代碼的字符串,再傳給exec語句執(zhí)行:
>>> modname='string'
>>> exec "import "+modname
exec語句以及和他類似eval會編譯一段字符串代碼,將其傳給Python解析器來執(zhí)行。
3)from復(fù)制變量名,而不是連接
from語句其實是在導(dǎo)入者的作用域內(nèi)對變量名的賦值語句,也就是變量名拷貝運算,而不是變量名的別名機(jī)制。它的實現(xiàn)和python所有賦值運算都一樣,微妙之處在于,共享對象的代碼存在于不同的文件中。然后,我們使用import獲得了整個模塊,然后賦值某個點號運算的變量名,就會修改導(dǎo)入的模塊中的變量名。點號運算把python定向到了模塊對象,而不是賦值模塊中對象。
4)from*會讓變量語義模糊
5)reload不會影響from導(dǎo)入
6)不要使用reload、from以及交互模式測試
reload中引用模塊得通過import至少將其加載一次:
不要from導(dǎo)入之后reload
7) reload使用沒有傳遞性
當(dāng)重載一個模塊時,Python只會重載那個模塊的文件,不會自動重載該文件重載嘶碰巧還要導(dǎo)入的模塊。
8)遞歸形式的from import無法工作
不要在遞歸導(dǎo)入中使用 from。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多