1. 程式人生 > >三元表達式、列表推導式、生成器表達式、遞歸、內置函數、匿名函數

三元表達式、列表推導式、生成器表達式、遞歸、內置函數、匿名函數

改變 現在 lose 知識庫 數據結構實現 結果 VM 情況 www.

一、三元表達式

name=input(姓名>>: )
res=SB if name == alex else NB
print(res)

二、列表推導式和生成器表達式

技術分享圖片
#老男孩由於峰哥的強勢加盟很快走上了上市之路,alex思來想去決定下幾個雞蛋來報答峰哥

egg_list=[雞蛋%s %i for i in range(10)] #列表解析

#峰哥瞅著alex下的一筐雞蛋,捂住了鼻子,說了句:哥,你還是給我只母雞吧,我自己回家下

laomuji=(雞蛋%s %i for i in range(10))#生成器表達式
print(laomuji)
print
(next(laomuji)) #next本質就是調用__next__ print(laomuji.__next__()) print(next(laomuji))
峰哥和alex的故事

總結:

1.把列表解析的[]換成()得到的就是生成器表達式

2.列表解析與生成器表達式都是一種便利的編程方式,只不過生成器表達式更節省內存

3.Python不但使用叠代器協議,讓for循環變得更加通用。大部分內置函數,也是使用叠代器協議訪問對象的。例如, sum函數是Python的內置函數,該函數使用叠代器協議訪問對象,而生成器實現了叠代器協議,所以,我們可以直接這樣計算一系列值的和:

sum(x ** 2 for
x in range(4))

而不用多此一舉使用如下方式

sum([x ** 2 for x in range(4)])

三、遞歸

1. 遞歸調用的定義

遞歸調用是函數嵌套調用的一種特殊形式,函數在調用時,直接或間接調用了自身,就是遞歸調用

2. 遞歸的最大深度-997

一個簡單的故事:從前有個山,山裏有座廟,廟裏老和尚講故事, 講的什麽呢?這個故事我們可以一直講下去

def story():
    s = """
    從前有個山,山裏有座廟,廟裏老和尚講故事,
    講的什麽呢?
    """
    print(s)
    story()
    
story()

可以看出如果遞歸函數沒有遇到外力的阻止,會一直進行下去,而函數的執行,會不斷的在內存中開辟名稱空間,而處於一個無限調用開辟的過程中,而造成內存不足,python為了杜絕此類事情的發生,強制將遞歸的層數限制在997,如下可以測試得知

技術分享圖片
def foo(n):
    print(n)
    n += 1
    foo(n)
foo(1)
測試遞歸最大深度

由此可見未報錯之前是997,為了實現我們程序的優化而設置為997,當然此值是可以更改的

技術分享圖片
import sys
print(sys.setrecursionlimit(100000))
修改遞歸最大深度

此處說明一點,如果遞歸深度為997都沒有得到你的程序想要的結果,則說明你的程序寫的確實比較爛。。。

看到此處我們或許覺得遞歸沒有while True好用,江湖人稱:人理解循環,神理解遞歸,所以不容小看遞歸,之後的很多算法都和遞歸有關,所以必須掌握遞歸。

3. 理解遞歸的思想

現在你們問我,alex老師多大了?我說我不告訴你,但alex比 egon 大兩歲。

你想知道alex多大,你是不是還得去問egon?egon說,我也不告訴你,但我比武sir大兩歲。

你又問武sir,武sir也不告訴你,他說他比金鑫大兩歲。

那你問金鑫,金鑫告訴你,他40了。。。

這個時候你是不是就知道了?alex多大?

我們用等式來說明這個問題

age(4) = age(3) + 2 
age(3) = age(2) + 2
age(2) = age(1) + 2
age(1) = 40

對於這樣的情況我們用函數如何表現呢?

def foo(n):
    if n==1:
        return 40
    else:
        return foo(n-1)+2

print(foo(4))

4. 總結遞歸調用

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

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

  3. 遞歸效率不高,遞歸層次過多會導致棧溢出(在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出)

四、內置函數

#註意:內置函數id()可以返回一個對象的身份,返回值為整數。這個整數通常對應與該對象在內存中的位置,但這與python
的具體實現有關,不應該作為對身份的定義,即不夠精準,最精準的還是以內存地址為準。is運算符用於比較兩個對象的身份,
等號比較兩個對象的值,內置函數type()則返回一個對象的類型

#更多內置函數:https://docs.python.org/3/library/functions.html?highlight=built#ascii 

技術分享圖片

上面就是內置函數的表,68個函數都在這兒了。這個表的順序是按照首字母的排列順序來的,你會發現都混亂的堆在一起。比如,oct和bin和hex都是做進制換算的,但是卻被寫在了三個地方。。。這樣非常不利於大家歸納和學習。那我把這些函數分成了6大類。你看下面這張圖,你猜咱們今天會學哪幾大類呀?

技術分享圖片

1. 作用域關系

技術分享圖片

基於字典的形式獲取局部變量和全局變量

globals()——獲取全局變量的字典

locals()——獲取執行本方法所在命名空間內的局部變量的字典

2. 其他

技術分享圖片

技術分享圖片
#1、語法
# eval(str,[,globasl[,locals]])
# exec(str,[,globasl[,locals]])

#2、區別
#示例一:
s=1+2+3
print(eval(s)) #eval用來執行表達式,並返回表達式執行的結果
print(exec(s)) #exec用來執行語句,不會返回任何值
‘‘‘
6
None
‘‘‘

#示例二:
print(eval(1+2+x,{x:3},{x:30})) #返回33
print(exec(1+2+x,{x:3},{x:30})) #返回None

# print(eval(‘for i in range(10):print(i)‘)) #語法錯誤,eval不能執行表達式
print(exec(for i in range(10):print(i)))
eval和exec 技術分享圖片
compile(str,filename,kind)
filename:用於追蹤str來自於哪個文件,如果不想追蹤就可以不定義
kind可以是:single代表一條語句,exec代表一組語句,eval代表一個表達式
s=for i in range(10):print(i)
code=compile(s,‘‘,exec)
exec(code)


s=1+2+3
code=compile(s,‘‘,eval)
eval(code)
complie(了解即可)

輸入輸出相關:

input() 輸入

技術分享圖片
s = input("請輸入內容 : ")  #輸入的內容賦值給s變量
print(s)  #輸入什麽打印什麽。數據類型是str
input用法

print() 輸出

技術分享圖片
def print(self, *args, sep= , end=\n, file=None): # known special case of print
    """
    print(value, ..., sep=‘ ‘, end=‘\n‘, file=sys.stdout, flush=False)
    file:  默認是輸出到屏幕,如果設置為文件句柄,輸出到文件
    sep:   打印多個值之間的分隔符,默認為空格
    end:   每一次打印的結尾,默認為換行符
    flush: 立即把內容輸出到流文件,不作緩存
    """
print源碼解析 技術分享圖片
f = open(tmp_file,w)
print(123,456,sep=,,file = f,flush=True)
file關鍵字的說明 技術分享圖片
import time
for i in range(0,101,2):  
     time.sleep(0.1)
     char_num = i//2      #打印多少個‘*‘
     per_str = \r%s%% : %s\n % (i, * * char_num) if i == 100 else \r%s%% : %s%(i,**char_num)
     print(per_str,end=‘‘, flush=True)
#小越越  : \r 可以把光標移動到行首但不換行
打印進度條

數據類型相關:

type(o) 返回變量o的數據類型

內存相關:

id(o) o是參數,返回一個變量的內存地址

hash(o) o是參數,返回一個可hash變量的哈希值,不可hash的變量被hash之後會報錯。

技術分享圖片
t = (1,2,3)
l = [1,2,3]
print(hash(t))  #可hash
print(hash(l))  #會報錯

‘‘‘
結果:
TypeError: unhashable type: ‘list‘
hash實例

hash函數會根據一個內部的算法對當前可hash變量進行處理,返回一個int數字。

*每一次執行程序,內容相同的變量hash值在這一次執行過程中不會發生改變。

文件操作相關

open() 打開一個文件,返回一個文件操作符(文件句柄)

操作文件的模式有r,w,a,r+,w+,a+ 共6種,每一種方式都可以用二進制的形式操作(rb,wb,ab,rb+,wb+,ab+)

可以用encoding指定編碼.

模塊操作相關

__import__導入一個模塊

技術分享圖片
import time
導入模塊 技術分享圖片
os = __import__(os)
print(os.path.abspath(.))
__import__

幫助方法

在控制臺執行help()進入幫助模式。可以隨意輸入變量或者變量的類型。輸入q退出

或者直接執行help(o),o是參數,查看和變量o有關的操作。。。

和調用相關

callable(o),o是參數,看這個變量是不是可調用。

如果o是一個函數名,就會返回True

技術分享圖片
def func():pass
print(callable(func))  #參數是函數名,可調用,返回True
print(callable(123))   #參數是數字,不可調用,返回False
callable實例

查看參數所屬類型的所有內置方法

dir() 默認查看全局空間內的屬性,也接受一個參數,查看這個參數內的方法或變量

技術分享圖片
print(dir(list))  #查看列表的內置方法
print(dir(int))  #查看整數的內置方法
查看變量/數據類型的內置方法

3. 和數字相關

技術分享圖片

數字——數據類型相關:bool,int,float,complex

數字——進制轉換相關:bin,oct,hex

數字——數學運算:abs,divmod,min,max,sum,round,pow

4. 和數據結構相關

技術分享圖片

序列——列表和元組相關的:list和tuple

序列——字符串相關的:str,format,bytes,bytearry,memoryview,ord,chr,ascii,repr

技術分享圖片
ret = bytearray(alex,encoding=utf-8)
print(id(ret))
print(ret[0])
ret[0] = 65
print(ret)
print(id(ret))
bytearray 技術分享圖片
ret = memoryview(bytes(你好,encoding=utf-8))
print(len(ret))
print(bytes(ret[:3]).decode(utf-8))
print(bytes(ret[3:]).decode(utf-8))
memoryview

序列:reversed,slice

技術分享圖片
 l = (1,2,23,213,5612,342,43)
print(l)
print(list(reversed(l)))
reversed 技術分享圖片
l = (1,2,23,213,5612,342,43)
sli = slice(1,5,2)
print(l[sli])
slice

數據集合——字典和集合:dict,set,frozenset

數據集合:len,sorted,enumerate,all,any,zip,filter,map

fileter 和 map

filter()函數接收一個函數 f 和一個list,這個函數 f 的作用是對每個元素進行判斷,返回 True或 False,filter()根據判斷結果自動過濾掉不符合條件的元素,返回由符合條件元素組成的新list。

例如,要從一個list [1, 4, 6, 7, 9, 12, 17]中刪除偶數,保留奇數,首先,要編寫一個判斷奇數的函數:

def is_odd(x):
    return x % 2 == 1

然後,利用filter()過濾掉偶數:

>>>filter(is_odd, [1, 4, 6, 7, 9, 12, 17])

結果:

[1, 7, 9, 17]

利用filter(),可以完成很多有用的功能,例如,刪除 None 或者空字符串:

def is_not_empty(s):
    return s and len(s.strip()) > 0
>>>filter(is_not_empty, [‘test‘, None, ‘‘, ‘str‘, ‘  ‘, ‘END‘])

結果:

[test, str, END]

註意: s.strip(rm) 刪除 s 字符串中開頭、結尾處的 rm 序列的字符。

當rm為空時,默認刪除空白符(包括‘\n‘, ‘\r‘, ‘\t‘, ‘ ‘),如下:

>>> a =  123
>>> a.strip()
123

>>> a = \t\t123\r\n
>>> a.strip()
123

練習:

請利用filter()過濾出1~100中平方根是整數的數,即結果應該是:

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

方法:

import math
def is_sqr(x):
    return math.sqrt(x) % 1 == 0
print filter(is_sqr, range(1, 101))

結果:

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

map

Python中的map函數應用於每一個可叠代的項,返回的是一個結果list。如果有其他的可叠代參數傳進來,map函數則會把每一個參數都以相應的處理函數進行叠代處理。map()函數接收兩個參數,一個是函數,一個是序列,map將傳入的函數依次作用到序列的每個元素,並把結果作為新的list返回。

有一個list, L = [1,2,3,4,5,6,7,8],我們要將f(x)=x^2作用於這個list上,那麽我們可以使用map函數處理。

>>> L = [1,2,3,4,] 
>>> def pow2(x): 
... return x*x 
... 
>>> map(pow2,L) 
[1, 4, 9, 16] 

sorted

對List、Dict進行排序,Python提供了兩個方法
對給定的List L進行排序,
方法1.用List的成員函數sort進行排序,在本地進行排序,不返回副本
方法2.用built-in函數sorted進行排序(從2.4開始),返回副本,原始輸入不變

--------------------------------sorted---------------------------------------

sorted(iterable, key=None, reverse=False)
Return a new list containing all items from the iterable in ascending order.

A custom key function can be supplied to customise the sort order, and the
reverse flag can be set to request the result in descending order.


-----------------------------------------------------------------------------
參數說明:
iterable:是可叠代類型;
key:傳入一個函數名,函數的參數是可叠代類型中的每一項,根據函數的返回值大小排序;
reverse:排序規則. reverse = True 降序 或者 reverse = False 升序,有默認值。
返回值:有序列表 例: 列表按照其中每一個值的絕對值排序 技術分享圖片
l1 = [1,3,5,-2,-4,-6]
l2 = sorted(l1,key=abs)
print(l1)
print(l2)
列表按照絕對值排序 技術分享圖片
l = [[1,2],[3,4,5,6],(7,),123]
print(sorted(l,key=len))
列表按照每一個元素的len排序 技術分享圖片
#字符串可以提供的參數 ‘s‘ None
>>> format(some string,s)
some string
>>> format(some string)
some string

#整形數值可以提供的參數有 ‘b‘ ‘c‘ ‘d‘ ‘o‘ ‘x‘ ‘X‘ ‘n‘ None
>>> format(3,b) #轉換成二進制
11
>>> format(97,c) #轉換unicode成字符
a
>>> format(11,d) #轉換成10進制
11
>>> format(11,o) #轉換成8進制
13
>>> format(11,x) #轉換成16進制 小寫字母表示
b
>>> format(11,X) #轉換成16進制 大寫字母表示
B
>>> format(11,n) #和d一樣
11
>>> format(11) #默認和d一樣
11

#浮點數可以提供的參數有 ‘e‘ ‘E‘ ‘f‘ ‘F‘ ‘g‘ ‘G‘ ‘n‘ ‘%‘ None
>>> format(314159267,e) #科學計數法,默認保留6位小數
3.141593e+08
>>> format(314159267,0.2e) #科學計數法,指定保留2位小數
3.14e+08
>>> format(314159267,0.2E) #科學計數法,指定保留2位小數,采用大寫E表示
3.14E+08
>>> format(314159267,f) #小數點計數法,默認保留6位小數
314159267.000000
>>> format(3.14159267000,f) #小數點計數法,默認保留6位小數
3.141593
>>> format(3.14159267000,0.8f) #小數點計數法,指定保留8位小數
3.14159267
>>> format(3.14159267000,0.10f) #小數點計數法,指定保留10位小數
3.1415926700
>>> format(3.14e+1000000,F)  #小數點計數法,無窮大轉換成大小字母
INF

#g的格式化比較特殊,假設p為格式中指定的保留小數位數,先嘗試采用科學計數法格式化,得到冪指數exp,如果-4<=exp<p,則采用小數計數法,並保留p-1-exp位小數,否則按小數計數法計數,並按p-1保留小數位數
>>> format(0.00003141566,.1g) #p=1,exp=-5 ==》 -4<=exp<p不成立,按科學計數法計數,保留0位小數點
3e-05
>>> format(0.00003141566,.2g) #p=1,exp=-5 ==》 -4<=exp<p不成立,按科學計數法計數,保留1位小數點
3.1e-05
>>> format(0.00003141566,.3g) #p=1,exp=-5 ==》 -4<=exp<p不成立,按科學計數法計數,保留2位小數點
3.14e-05
>>> format(0.00003141566,.3G) #p=1,exp=-5 ==》 -4<=exp<p不成立,按科學計數法計數,保留0位小數點,E使用大寫
3.14E-05
>>> format(3.1415926777,.1g) #p=1,exp=0 ==》 -4<=exp<p成立,按小數計數法計數,保留0位小數點
3
>>> format(3.1415926777,.2g) #p=1,exp=0 ==》 -4<=exp<p成立,按小數計數法計數,保留1位小數點
3.1
>>> format(3.1415926777,.3g) #p=1,exp=0 ==》 -4<=exp<p成立,按小數計數法計數,保留2位小數點
3.14
>>> format(0.00003141566,.1n) #和g相同
3e-05
>>> format(0.00003141566,.3n) #和g相同
3.14e-05
>>> format(0.00003141566) #和g相同
3.141566e-05

format(了解即可)
format(了解即可) 技術分享圖片
字典的運算:最小值,最大值,排序
salaries={
    egon:3000,
    alex:100000000,
    wupeiqi:10000,
    yuanhao:2000
}

叠代字典,取得是key,因而比較的是key的最大和最小值
>>> max(salaries)
yuanhao
>>> min(salaries)
alex

可以取values,來比較
>>> max(salaries.values())
>>> min(salaries.values())
但通常我們都是想取出,工資最高的那個人名,即比較的是salaries的值,得到的是鍵
>>> max(salaries,key=lambda k:salary[k])
alex
>>> min(salaries,key=lambda k:salary[k])
yuanhao



也可以通過zip的方式實現
salaries_and_names=zip(salaries.values(),salaries.keys())

先比較值,值相同則比較鍵
>>> max(salaries_and_names)
(100000000, alex)


salaries_and_names是叠代器,因而只能訪問一次
>>> min(salaries_and_names)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: min() arg is an empty sequence



sorted(iterable,key=None,reverse=False)
!!! lambda與內置函數結合使用

五、匿名函數

匿名函數:為了解決那些功能簡單而設置的一句話函數

#這段代碼
def calc(n):
    return n**n
print(calc(10))
 
#換成匿名函數
calc = lambda n:n**n
print(calc(10))

技術分享圖片

上面是我們對calc這個匿名函數的分析,下面給出了一個關於匿名函數格式的說明

函數名 = lambda 參數 :返回值

#參數可以有多個,用逗號隔開
#匿名函數不管邏輯多復雜,只能寫一行,且邏輯執行結束後的內容就是返回值
#返回值和正常的函數一樣可以是任意數據類型

我們可以看出匿名函數並非真的沒有函數名,他的調用和函數的調用也就沒有區別,也是只需要 函數名(參數) 即可

上邊是匿名函數的函數用法,除此之外還可以匿名真的可以匿名,並和其他函數合作使用

l=[3,2,100,999,213,1111,31121,333]
print(max(l))

dic={k1:10,k2:100,k3:30}


print(max(dic))
print(dic[max(dic,key=lambda k:dic[k])])

有名函數與匿名函數的對比

#有名函數與匿名函數的對比
有名函數:循環使用,保存了名字,通過名字就可以重復引用函數功能

匿名函數:一次性使用,隨時隨時定義

應用:max,min,sorted,map,reduce,filter

課後作業

1 文件內容如下,標題為:姓名,性別,年紀,薪資

  egon male 18 3000

  alex male 38 30000

  wupeiqi female 28 20000

  yuanhao female 28 10000

要求:
從文件中取出每一條記錄放入列表中,
列表的每個元素都是{‘name‘:‘egon‘,‘sex‘:‘male‘,‘age‘:18,‘salary‘:3000}的形式

2 根據1得到的列表,取出薪資最高的人的信息。

3 根據1得到的列表,取出最年輕的人的信息。

4 根據1得到的列表,將每個人的信息中的名字映射成首字母大寫的形式。

5 根據1得到的列表,過濾掉名字以a開頭的人的信息。

6 使用遞歸打印斐波那契數列(前兩個數的和得到第三個數,如:0 1 1 2 3 4 7...)。

7 一個嵌套很多層的列表,如l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]],用遞歸取出所有的值

技術分享圖片
#1
with open(db.txt) as f:
    items=(line.split() for line in f)
    info=[{name:name,sex:sex,age:age,salary:salary}           for name,sex,age,salary in items]

print(info)
#2
print(max(info,key=lambda dic:dic[salary]))

#3
print(min(info,key=lambda dic:dic[age]))

# 4
info_new=map(lambda item:{name:item[name].capitalize(),
                          sex:item[sex],
                          age:item[age],
                          salary:item[salary]},info)

print(list(info_new))

#5
g=filter(lambda item:item[name].startswith(a),info)
print(list(g))

#6
#非遞歸
def fib(n):
    a,b=0,1
    while a < n:
        print(a,end= )
        a,b=b,a+b
    print()

fib(10)
#遞歸
def fib(a,b,stop):
    if  a > stop:
        return
    print(a,end= )
    fib(b,a+b,stop)

fib(0,1,10)


#7
l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]]

def get(seq):
    for item in seq:
        if type(item) is list:
            get(item)
        else:
            print(item)
get(l)
答案

三元表達式、列表推導式、生成器表達式、遞歸、內置函數、匿名函數