經常使用內置函數、三元運算、遞歸

經常使用內置函數

    Built-in Functions    
abs() dict() help() min() setattr()
all() dir() hex() next() slice()
any() divmod() id() object() sorted()
ascii() enumerate() input() oct() staticmethod()
bin() eval() int() open() str()
bool() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
classmethod() getattr() locals() repr() zip()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()  
delattr() hash() memoryview() set()  

abs/round/sum

>>> abs(1)
>>> abs(-1)         # 求絕對值
>>> round(1.234,2)
1.23
>>> round(1.269,2)  # 四捨五入
1.27
>>> sum([1,2,3,4])
>>> sum((1,3,5,7))  # 接收數字組成的元組/列表
>>> def func():pass  
>>> callable(func)   # 判斷一個變量是否能夠調用 函數能夠被調用
True
>>> a = 123          # 數字類型a不能被調用
>>> callable(a)
False
>>> chr(97)          # 將一個數字轉換成一個字母
'a'
>>> chr(65)
'A'
>>> dir(123)         # 查看數字類型中含有哪些方法
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
>>> dir('abc')
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

eval/exec

>>> eval('1+2-3*4/5')  # 執行字符串數據類型的代碼而且將值返回
0.6000000000000001
>>> exec('print(123)') # 執行字符串數據類型的代碼但沒有返回值
123

enumerate

>>> enumerate(['apple','banana'],1)   # 會給列表中的每個元素拼接一個序號
<enumerate object at 0x113753fc0>
>>> list(enumerate(['apple','banana'],1))
[(1, 'apple'), (2, 'banana')]

max/min

>>> max(1,2,3,)     # 求最小值
3
>>> min(2,1,3)      # 求最大值
1

sorted

將給定的可迭代對象進行排序,並生成一個有序的可迭代對象。html

>>> sorted([1, 4, 5, 12, 45, 67])  # 排序,並生成一個新的有序列表
[1, 4, 5, 12, 45, 67]

還接受一個key參數和reverse參數。python

>>> sorted([1, 4, 5, 12, 45, 67], reverse=True)
[67, 45, 12, 5, 4, 1]
list1 = [
    {'name': 'Zoe', 'age': 30},
    {'name': 'Bob', 'age': 18},
    {'name': 'Tom', 'age': 22},
    {'name': 'Jack', 'age': 40},
]

ret = sorted(list1, key=lambda x: x['age'])
print(ret)

# [{'name': 'Bob', 'age': 18}, {'name': 'Tom', 'age': 22}, {'name': 'Zoe', 'age': 30}, {'name': 'Jack', 'age': 40}]

zip

zip函數接收一個或多個可迭代對象做爲參數,最後返回一個迭代器:git

>>> x = ["a", "b", "c"]
>>> y = [1, 2, 3]
>>> a = list(zip(x, y))  # 合包
>>> a
[('a', 1), ('b', 2), ('c', 3)]
>>> b =list(zip(*a))  # 解包
>>> b
[('a', 'b', 'c'), (1, 2, 3)]

zip(x, y) 會生成一個可返回元組 (m, n) 的迭代器,其中m來自x,n來自y。 一旦其中某個序列迭代結束,迭代就宣告結束。 所以迭代長度跟參數中最短的那個序列長度一致。面試

>>> x = [1, 3, 5, 7, 9]
>>> y = [2, 4, 6, 8]
>>> for m, n in zip(x, y):
...   print(m, n)
... 
2
4
6
8

若是上面不是你想要的效果,那麼你還可使用 itertools.zip_longest() 函數來代替這個例子中的zip。算法

>>> from itertools import zip_longest
>>> x = [1, 3, 5, 7, 9]
>>> y = [2, 4, 6, 8]
>>> for m, n in zip_longest(x, y):
...   print(m, n)
... 
2
4
6
8
None

zip其餘常見應用:api

>>> keys = ["name", "age", "salary"]
>>> values = ["Andy", 18, 50]
>>> d = dict(zip(keys, values))
>>> d
{'name': 'Andy', 'age': 18, 'salary': 50}

map

map()接收兩個參數func(函數)和seq(序列,例如list)。以下圖:app

map()將函數func應用於序列seq中的全部元素。在Python3以前,map()返回一個列表,列表中的每一個元素都是將列表或元組「seq」中的相應元素傳入函數func返回的結果。Python 3中map()返回一個迭代器。ssh

由於map()須要一個函數做爲參數,因此能夠搭配lambda表達式很方便的實現各類需求。ide

例子1:將一個列表裏面的每一個數字都加100:函數

>>> l = [11, 22, 33, 44, 55]
>>> list(map(lambda x:x+100, l))
[111, 122, 133, 144, 155]

例子2:

使用map就至關於使用了一個for循環,咱們徹底能夠本身定義一個my_map函數:

def my_map(func, seq):
    result = []
    for i in seq:
        result.append(func(i))
    return result

測試一下咱們本身的my_map函數:

>>> def my_map(func, seq):
...     result = []
...     for i in seq:
...         result.append(func(i))
...     return result
... 
>>> l = [11, 22, 33, 44, 55]
>>> list(my_map(lambda x:x+100, l))
[111, 122, 133, 144, 155]

咱們自定義的my_map函數的效果和內置的map函數同樣。

固然在Python3中,map函數返回的是一個迭代器,因此咱們也須要讓咱們的my_map函數返回一個迭代器:

def my_map(func, seq):
    for i in seq:
        yield func(i)

測試一下:

>>> def my_map(func, seq):
...     for i in seq:
...         yield func(i)
... 
>>> l = [11, 22, 33, 44, 55]
>>> list(my_map(lambda x:x+100, l))
[111, 122, 133, 144, 155]

與咱們本身定義的my_map函數相比,因爲map是內置的所以它始終可用,而且始終以相同的方式工做。它也具備一些性能優點,一般會比手動編寫的for循環更快。固然內置的map還有一些高級用法:

例如,能夠給map函數傳入多個序列參數,它將並行的序列做爲不一樣參數傳入函數:

拿pow(arg1, arg2)函數舉例,

>>> pow(2, 10)
>>> pow(3, 11)
>>> pow(4, 12)
>>> list(map(pow, [2, 3, 4], [10, 11, 12]))
[1024, 177147, 16777216]

filter

filter函數和map函數同樣也是接收兩個參數func(函數)和seq(序列,如list),以下圖:

filter函數相似實現了一個過濾功能,它過濾序列中的全部元素,返回那些傳入func後返回True的元素。也就是說filter函數的第一個參數func必須返回一個布爾值,即True或者False。

下面這個例子,是使用filter從一個列表中過濾出大於33的數:

>>> l = [30, 11, 77, 8, 25, 65, 4]
>>> list(filter(lambda x: x>33, l))
[77, 65]

利用filter()還能夠用來判斷兩個列表的交集:

>>> x = [1, 2, 3, 5, 6]
>>> y = [2, 3, 4, 6, 7]
>>> list(filter(lambda a: a in y, x))
[2, 3, 6]

補充:reduce

reduce
注意:Python3中reduce移到了functools模塊中,你能夠用過from functools import reduce來使用它。

reduce一樣是接收兩個參數:func(函數)和seq(序列,如list),以下圖:

 

reduce最後返回的不是一個迭代器,它返回一個值。

reduce首先將序列中的前兩個元素,傳入func中,再將獲得的結果和第三個元素一塊兒傳入func,…,這樣一直計算到最後,獲得一個值,把它做爲reduce的結果返回。

原理相似於下圖:

 

看一下運行結果:

>>> from functools import reduce
>>> reduce(lambda x,y:x+y, [1, 2, 3, 4])
10

再來練習一下,使用reduce求1~100的和:

>>> from functools import reduce
>>> reduce(lambda x,y:x+y, range(1, 101))
5050

lambda

lambda是匿名函數,也就是沒有名字的函數。lambda的語法很是簡單:

直白一點說:爲了解決那些功能很簡單的需求而設計的一句話函數

注意:

使用lambda表達式並不能提升代碼的運行效率,它只能讓你的代碼看起來簡潔一些。

#這段代碼
def func(x, y):
    return x + y#換成匿名函數
lambda x, y:x+y

ambda表達式和定義一個普通函數的對比:

 

咱們能夠將匿名函數賦值給一個變量而後像調用正常函數同樣調用它。

匿名函數的調用和正常的調用也沒有什麼分別。 就是 函數名(參數) 就能夠了~~~

練一練:

請把如下函數變成匿名函數
def func(x, y):
    return x + y

上面是匿名函數的函數用法。除此以外,匿名函數也不是浪得虛名,它真的能夠匿名。在和其餘功能函數合做的時候

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])])
res = map(lambda x:x**2,[1,5,7,4,8])
for i in res:
    print(i)

輸出
25
16
res = filter(lambda x:x>10,[5,8,11,9,15])
for i in res:
    print(i)

輸出
15

面試題練一練

1.現有兩個元組(('a'),('b')),(('c'),('d')),請使用python中匿名函數生成列表[{'a':'c'},{'b':'d'}]

#答案一
test = lambda t1,t2 :[{i:j} for i,j in zip(t1,t2)]
print(test(t1,t2))
#答案二
print(list(map(lambda t:{t[0]:t[1]},zip(t1,t2))))
#還能夠這樣寫
print([{i:j} for i,j in zip(t1,t2)])
複製代碼
View Code
1.下面程序的輸出結果是:
d = lambda p:p*2
t = lambda p:p*3
x = 2
x = d(x)
x = t(x)
x = d(x)
print x



 練習2
View Code

三元運算

三元運算(三目運算)在Python中也叫條件表達式。三元運算的語法很是簡單,主要是基於True/False的判斷。以下圖:

 

使用它就能夠用簡單的一行快速判斷,而再也不須要使用複雜的多行if語句。 大多數時候狀況下使用三元運算可以讓你的代碼更清晰。

三元運算配合lambda表達式和reduce,求列表裏面值最大的元素:

>>> from functools import reduce
>>> l = [30, 11, 77, 8, 25, 65, 4]
>>> reduce(lambda x,y: x if x > y else y, l)
77

再來一個,三元運算配合lambda表達式和map的例子:

將一個列表裏面的奇數加100:

>>> l = [30, 11, 77, 8, 25, 65, 4]
>>> list(map(lambda x: x+100 if x%2 else x, l))
[30, 111, 177, 8, 125, 165, 4]

遞歸

遞歸是一種解決問題的思路。

在函數內部,能夠調用其餘函數。若是一個函數在內部調用自身自己,這個函數就是遞歸函數。

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

初識遞歸

遞歸的定義—— 在一個函數裏再調用這個函數自己

如今咱們已經大概知道剛剛講的story函數作了什麼,就是 在一個函數裏再調用這個函數自己 ,這種魔性的使用函數的方式就叫作 遞歸 

剛剛咱們就已經寫了一個最簡單的遞歸函數。

遞歸的最大深度——1000

正如大家剛剛看到的,遞歸函數若是不受到外力的阻止會一直執行下去。

可是咱們以前已經說過關於函數調用的問題,每一次函數調用都會產生一個屬於它本身的名稱空間,若是一直調用下去,就會形成名稱空間佔用太多內存的問題。

Python爲了杜絕此類現象,強制的將遞歸層數控制在了1000 (你寫代碼測試可能只測出997或998)。

咱們能夠經過下面的代碼來查看此限制:

import sys
print(sys.getrecursionlimit())

1000是Python爲了咱們程序的內存優化所設定的一個默認值,咱們固然還能夠經過一些手段去修改它:

import sys
print(sys.setrecursionlimit(100000))

咱們能夠經過這種方式來修改遞歸的最大深度,剛剛咱們將Python容許的遞歸深度設置爲了10w,至於實際能夠達到的深度就取決於計算機的性能了。

不過咱們仍是很是不推薦修改這個默認的遞歸深度,由於若是用1000層遞歸都沒有解決的問題要麼是不適合使用遞歸來解決要麼就是你代碼寫的太爛了~~~

江湖上流傳這這樣一句話叫作:人理解循環,神理解遞歸。

注意Python解釋器不支持尾遞歸優化。

再談遞歸

這裏咱們又要舉個例子來講明遞歸能作的事情。

 

首先咱們須要記住構成遞歸需具有的條件:

1. 子問題須與原始問題爲一樣的事,且更爲簡單(問題相同,但規模在變小);

2. 不能無限制地調用自己,須有個出口,化簡爲非遞歸情況處理。

總結一下:

遞歸是用來解決那些問題能夠簡化爲不少相同的規模小不少的子問題的場景。

就是把大問題分紅小問題,小問題本質上合大問題是同樣的問題。

好比:list1 = [1, [2, [3, [4, [5, [6, [7, [8, [9]]]]]]]]],把裏面的每個數字都打印出來。

def tell(x):
    for i in x:
        if not isinstance(i, list):
            print(i)
        else:
            tell(i)
            
            
tell(list1)

遞歸函數的優勢是定義簡單,邏輯清晰。理論上,全部的遞歸函數均可以寫成循環的方式,但循環的邏輯不如遞歸清晰。

再好比斐波那契數列,這種典型的可使用遞歸解決的問題,均可以清晰的分爲回溯和遞推兩個階段。

遞歸函數與二分查找算法

http://www.javashuo.com/article/p-zhmqnlqb-dn.html

相關文章
相關標籤/搜索