第四天 內置函數2 隨機碼 裝飾器 迭代器、生成器 遞歸 冒泡算法 JSON

 

關於函數的returnpython

 

li = [11,22,33,44]算法

 

def f1(arg):json

    arg.append(55)數據結構

 

li = f1(li)app

 

print(li)dom

 

由於li = f1(li) 實際賦值的是f1的return,那麼在這種狀況下函數f1並未定義return,因此默認返回Nonepython2.7

 

所以li的值應該是none函數

 

 

 

若是是編碼

 

li = [11,22,33,44]對象

 

def f1(arg):

    arg.append(55)

 

f1(li)

 

print(li)

 

由於函數傳遞的參數實際是參數的引用,所以在函數中對參數坐的變動會影響原來的參數,所以返回的是11,22,33,44,55

 

 

 

 

將字符串轉換爲特定編碼的字節類型

 

s = "劉博"

bytes(s,encoding="utf-8")

 

 

 

內置函數補充

 

callable() 判斷對象是否能夠被執行,函數能夠被執行

 

 

 

chr()  將編碼表中的序列轉化爲對應的字符,2.7內特指ASCII碼

ord()  將編碼表中的字符轉化爲對應的序號,2.7內特製ASCII碼

 

 

 

隨機驗證碼

 

import random #這個函數用來隨機生成數字

 

tem = random.randrange(65,91) #指定隨機生成數字的範圍

 

c = chr(tem) #而後咱們可使用chr(i)的方式將i轉換爲對應的字符

 

在ASCII碼錶中65 - 91表明的是26個字母的大小寫

 

若是一次生成多位的隨機碼,則能夠按以下寫法

li = []

for i in range(6):

    tem = random.randrange(65,91)

    c = chr(tem)

    li.append(c)

"".join(li)   #將生成的列表造成字符串

 

 

若是須要有數字則

 

li = []

for i in range(6):

    if  i == 2 or i == 4:

        tem = random.randrange(0,10)

        li.append(str(tem))        #由於在向列表中添加元素時,須要使用字符串類型,所以ASCII中0-10是數字所以須要將其轉爲字符串類型

    else:

        tem = random.randrange(65,91)

        c = chr(tem)

        li.append(c)

result = "".join(li)   #將生成的列表造成字符串

print(result)

 

 

上面的例子中數字的位置是固定的,若是但願將隨機數作的跟完全即數字的位置都是隨機的

 

li = []

for i in range(6):

    r = random.randrange(0,6)

    if  r == 3 or r == 2:

        tem = random.randrange(0,10)

        li.append(str(tem))        #由於在向列表中添加元素時,須要使用字符串類型,所以ASCII中0-10是數字所以須要將其轉爲字符串類型

    else:

        tem = random.randrange(65,91)

        c = chr(tem)

        li.append(c)

result = "".join(li)   #將生成的列表造成字符串

print(result)

 

 

 

 

 

 

complie() 

eval()

exec()

 

任何一個python文件,計算機都要通過讀取成字符串,編譯,執行三個階段。

 

complie()就是用來編譯這個字符串的動做

s = "print(123)"         #s的值是字符串

r = complie(s,"<string>","exec)"   #r的值就是s編譯後的結果,其中complie中s的位置也能夠是一個文件名,若是是文件名就不須要後面的string參數,exec參數有3種值:single eval exec。其中若是選擇single模式,則拿到的字符串會編譯成單行的程序,若是是eval則會編譯成表達式,若是是exec則按照原來的python代碼編譯

 

exec() 用來執行編譯後的代碼,和complie何用,先用complie編譯,而後用exec執行。exec能夠執行全部的python的命令,exec只是執行沒有返回值,所以用exec運行一個表達式,是拿不到結果的,例如exec(「7+8+9」),只是執行可是結果是拿不到的。在執行代碼的時候exec能夠接受代碼或者字符串。

 

eval()用來將字符串編譯爲表達式,例如  s = "8*8"  r = eval(s) , print(r)的時候會返回爲64,eval只能執行表達式,eval有返回值,若是用eval(「7+8+9」),是能返回結果的,這點比exec強,對比exec。

 

 

 

dir() 快速獲取一個對象 一個類中的功能   print(dir(dict)),查看字典這個函數中提供的功能

 

help() 獲取一個對象提供的功能的詳細解釋,dir僅介紹功能名,help有解釋。

 

divmod()  用來以元組的形式獲取一個數除以另外一個數的整數和餘數,r = divmod(97,10) ,print(r) 返回(9,7),由於默認返回永遠都是2個數,所以可使用n1,n2 = divmod(97,10) 會自動給n1 = 9 ,n2 = 7

 

enumerate() 序列化

 

instance()  對象是類的實例,即 s = 「alex」 那麼alex是基於str這個類建立的對象,所以alex就是類str的一個實例,類是一個模板,而對象是對這個模板的實例。s = "alex"  r = isinstance(s,str)判斷s是不是str這個類的實例,print(r)會返回True

 

filter() filter(函數,可迭代對象) 在執行filter的時候,首先會循環可迭代對象,在每次循環的內部會執行第一個參數所填寫的函數,並拿到函數的結果,若是結果爲真,則會把此次循環的元素添加到一個列表中

li = [11,22,33,44]

def f1(a)

    if a > 22

        return True

 

ret = filter(f1,li)

print(list(ret))

 

會返回[33,44],所以filter是基於提供的函數對可迭代對象進行篩選。

上面的filter而已用lambda表達式來實現

 

li = [11,22,33,44]

ret = filter(lambda a : a>22,li)

print(list(ret))

 

 

 

map() map(函數,可迭代對象),在執行map的時候,首先會循環可迭代函數,而後再每次循環的結果代入以前傳遞的函數中,並運行函數中定義的返回結果,將其追加到一個新的列表中

 

 

li = [11,22,33,44]

def f1(a):

    return a + 100

ret = map(f1,li)

 

print(list(ret))

 

結果就是[111,122.133.144]

 

一樣可使用lambda表達式

 

li = [11,22,33,44]

ret = map(lambda a : a+100 ,li]

print(list(ret))

 

 

 

filter() 函數的返回爲True,則將結果加入列表

map() 將函數的結果加入列表

 

 

 

 

globals() 表明全部的全局變量,輸出類型爲字典,print(globals())打印當前代碼中全部的全局變量以字典類型輸出

locals() 表明全部的局部變量,輸出類型爲字典,print(local())打印當前代碼中全部的局部變量以字典類型輸出

 

hash() 生成對應內容的hash值   s=123 print(hash(s)),在python存儲字典key的時候都是現將key進行hash算法以後再存儲,由於hash算法算出的值是一個固定長度的,所以不管key有多長實際在存儲時是一樣長度的值。全部的語言都是這麼操做的。這樣有利於存儲,也有利於查找。

 

len() 查看變量的長度,在python3中按照字符計算,在python2.7中按字節計算,所以在python3中若是想要按字節算長,應先將變量變爲字節。

s = 「李傑」

print(len(s))  結果爲2按字符,

 

s = 「李傑」

b = bytes(s,encoding=「utf-8」)

print(b)         結果爲6按字節

 

max() 查找序列中的最大值

min() 查找序列中的最小值

sum() 序列求和

 

 

memoryview() 和內存地址相關的一個類

 

object() 是全部類的父類

 

pow() 求平方,通常寫法爲2**10表明2的10次方,同時也看而已寫爲pow(2,10)

 

range() 指定一個範圍

 

reversed() 翻轉

 

round()  將一個小數四捨五入

 

slice() 切片

 

sort() 排序 sort(列表) 等於 列表.sort

 

zip()  傳入多個列表,zip會將全部列表的第一個元素拼爲一個元組,第二個元素拼爲一個元組以此類推。當元素長度不同的時候,只會拼接到列表 元素最少的那個位置

 

l1=["liubo",23,19]

l2=[33,55]

l3=["aa","cc",22,55]

l4=zip(l1,l2,l3)

print(list(l4))

輸出結果爲

[('liubo', 33, 'aa'), (23, 55, 'cc')]  # 只到了拼接到第二個元素,由於l2只有2個元素

 

 

 

 

深色框是要會的,打勾的是用的比較經常使用的

 

 

JSON 能夠將能夠將字符串根據其形式轉換爲對應的類型,也能夠將對應類型的數據按照原格式轉換爲字符串

 

s = "[11,22,33,44]"   # 這是一個字符串而不是列表

n = json.loads(s)  # 經過這種方法,就將s的字符串轉換成了列表,字典也能夠,能夠將文件中對應的格式寫入python成爲特定的數據類型

 

s = [11,22,33]  # 這是一個列表

n = json.dumps(s) # 經過這個就能夠將其轉化爲字符串,可是格式仍然是列表的格式就像上例中的s ,好比能夠用他來說內容寫入文件,寫入文件必需要字符串 

 

轉換一般元組是不行的,由於轉化是跨語言的,可是元組的()是python獨有的

使用轉換時,若是想要經過loads將字符串轉換成字典或列表,那麼裏面的字符串內部的字符串元素必須用雙引號

 

 

 

裝飾器

 

函數開發有開放封閉規則,即對函數自己是封閉的不能被隨便改寫,可是在外部是能夠開放調用這個函數的。可是若是要批量修改多個函數,就須要用到裝飾器。即在不改變原有函數的狀況下,增長函數的功能

 

定義一個s1.py,代碼以下

def outer(func):

    def inner():

        print("log")

        return func()

    return inner

 

@outer

def f1():

    print("F1")

 

@outer

def f2():

    print("F2")

 

 

@outer

def f3():

    print("F3")

 

這樣當別人在經過調用f1函數時會首先執行outer函數中的功能。outer函數就是裝飾器,在不改變f1函數功能的狀況下,經過裝飾器增長了f1函數的功能。

 

調用方法:

新建一個py文件

import s1       # 將以前建立的s1導入到代碼中

s1.f1() # 調用s1代碼中的f1函數

 

結果是

log # outer裝飾器的輸出

F1 # f1函數的輸出

 

 

裝飾器必備知識點:

 

一、

def f1():

    print(123)

 

def f1():

    print(456)
 

f1()

此時執行f1會打印456,由於python是一行一行加載代碼,所以第二次f1會將f1指向print(456)的方法

 

 

二、

def f1():

    print(123)

 

def f2(xxx):

    xxx()

 

 

f2(f1)

 

函數的參數能夠是另外一個函數,所以輸出123

 

 

@ + 函數名 就是裝飾器

@outer的功能

一、自動執行outer函數而且將它下面的函數名f1當作參數傳遞(函數名代指整個函數,函數名()纔是執行函數)

二、將outer函數的返回值從新賦值給f1

 

所以:

 

def outer(func):

    def inner():

        print("before")

    return inner

 

@outer

def f1():
    print("F1")

 

執行上面的函數的過程是

一、首先系統會自動執行outer函數,並將f1做爲參數傳遞給outer函數

二、outer函數內部定義了一個新的函數inner,該函數打印before

三、outer函數返回了inner函數

四、outer函數將返回值inner函數從新賦值給f1

五、此時f1()的函數內容被替換爲了inner的內容

六、所以執行f1()函數時打印before而不是F1

 

 

 

所以實際上裝飾器就是講@下一行的函數f1替換爲outer返回的函數。那麼咱們執行以前的操做經過裝飾器在某個函數以前或以後增長功能的操做實際上就是outer的內層函數的做用

 

def outer(func):

    def inner():

        print("before")

        func()

   print("after")

    return inner

 

@outer

def f1():

    print(123)

 

在上面outer函數內層函數中的func實際就是f1的原函數體,由於@outer將f1的原函數體傳遞給了func參數。所以在內層函數的操做就是在執行f1以前先執行before而後執行f1最後執行after

 

 

 

定義函數,未調用,函數內部不執行

 

函數名代指整個函數,函數名()纔是執行函數

 

def outer(func):

    def inner():

        print("before")

        func()

   print("after")

    return inner

 

@outer

def f1():

    print(123)

所以這個例子中,outer函數的返回值必須是inner而不是inner(),由於這樣作的目的時要將inner這個函數的函數體返回給f1,不然若是return inner(),則是返回的inner函數定義的返回值,而這個函數咱們並未指定返回,默認返回爲None。這樣函數f1也就被替換爲none。即使inner定義了返回值,也不是咱們所要的。咱們要的是inner函數體而不是返回值

 

 

 

若是原函數定義了返回值

那麼在裝飾器中的函數inner就會沒有返回值,由於inner中只執行了func()而沒有獲取他的返回值。所以須要咱們將這個返回值獲取到

因此完整的裝飾器寫法應該入下

 

 

def outer(func):

    def inner():

        print("before")

        r = func() # 執行原函數,並獲取原函數返回值

   print("after")

   return r  # 將原函數的返回值返回    

    return inner

 

 

 

若是原函數定義了參數

 

裝飾器的函數應該使用萬能參數來解決原函數帶參數的問題。

 

def outer(func):

    def inner(*args,**kwargs):

        print("before")

        r = func(*args,**kwargs) # 此處python會直接將inner中的參數傳遞到func中。

   print("after")

   return r  # 將原函數的返回值返回    

    return inner

 

 

 

 

 

 

遞歸

 

一個函數在內部調用本身,就是遞歸。

遞歸特性的要求:

一、必須有一個明確的結束條件

 

 

 

二、每次進入更深一層遞歸時,問題規模相比上次遞歸都應有所減小

 

 

 

三、遞歸效率不高,遞歸層次過多會致使棧溢出(在計算機中,函數調用是經過棧這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。因爲棧的大小不是無限的,因此遞歸調用次數過多,會致使棧 溢出)

相關文章
相關標籤/搜索