python基礎--函數全解析(2)

函數的重點知識補充

(1)補充的兩個小知識點(global,nonlocal)

1.global的使用

咱們在補充這兩個知識點以前,咱們先看一下下面這個例子:python

a = 1
def func():
    print(a) # 1
func()
a = 1
def func():
    # 這裏不可以對更改全局做用域變量的值。只可以賦值。否則會報出下面的錯誤。
    a += 1 # 報錯 UnboundLocalError: local variable 'a' referenced before assignment
func()

局部做用域對全局做用域的變量(此變量只能是不可變的數據類型)只能進行引用,而不能進行改變,只要改變就會報錯,可是有些時候,咱們程序中會遇到局部做用域去改變全局做用域的一些變量的需求,這怎麼作呢?這就得用到關鍵字global:面試

global第一個功能:在局部做用域中能夠更改全局做用域的變量。數組

global第二個功能:利用global在局部做用域也能夠聲明一個全局變量。緩存

# 這是一個十分重要的例子。必定要深入的體會。
count = 1
count1 = 2

def search():
    global count # 將count變量變爲全局的,而後能夠在函數體(局部做用域)中能夠更改全局做用域的變量。
    count += 2 # 那麼咱們如今就能夠對全局變量count的值進行修改。

def search1():
    global count1 # 將count1變量變爲全局的,而後能夠在函數體(局部做用域)中能夠更改全局做用域的變量。
    count = 6 # 若是沒有global這個關鍵字,那麼咱們不能夠對count的值進行修改操做,只能夠進行賦值的操做。
    count1 = 5 # 那麼咱們如今就能夠對全局變量count1的值進行賦值修改。
    print(count) # 6
    print(count1) # 5
search()
print(count) # 3 這裏打印count的時候,取值是從全局做用域開始找--》到內置做用域結束。這裏的count在前面已經被更改了(global count count += 2),因此這裏輸出的結果爲3
search1()
print(count) # 3 這裏打印count的時候,取值是從全局做用域開始找--》到內置做用域結束。這裏的count在前面已經被更改了(global count count += 2),因此這裏輸出的結果爲3
print(count1) # 5 這裏打印count的時候,取值是從全局做用域開始找--》到內置做用域結束。這裏的count在前面已經被更改了(global count1 count1 = 5),因此這裏輸出的結果爲5

因此global關鍵字有兩個做用:函數

1.聲明一個全局變量。源碼分析

2.在局部做用域想要對全局做用域的全局變量進行修改時,須要用到 global(限於字符串,數字)。編碼

2.nonlocal的使用

nonlocal是python3x新加的功能,與global用法差很少,就是在局部做用域若是想對父級做用域的變量進行改變時,須要用到nonlocal。code

def add_b():
    b = 42
    def do_global():
        b = 10
        print(b)
        def dd_nonlocal():
            nonlocal b
            b = b + 20
            print(b)
        dd_nonlocal()
        print(b)
    do_global()
    print(b)
add_b()
# 輸出的結果爲:
# 10
# 30
# 30
# 42

nonlocal的總結:orm

1.不能更改全局變量。對象

2.在局部做用域中,對父級做用域(或者更外層做用域非全局做用域)的變量進行引用和修改,而且引用的哪層,從那層及如下此變量所有發生改變。

(2)函數名的應用

函數名的理解:函數名的定義和變量的定義幾乎一致,在變量的角度,函數名其實就是一個變量,具備變量的功能:能夠賦值;可是做爲函數名他也有特殊的功能就是加上()就會執行對應的函數,因此咱們能夠把函數名當作一個特殊的變量,那麼接下來,咱們就來研究一下這個特殊的變量。

def func():
    a = 1
    b = 2
    print(a)
    print(a+b)

print(func) # <function func at 0x000001FBBA424678>
# 註釋,函數名至關於變量,函數名指向的是函數的內存地址,,其實深一步理解可得知,與其說函數名()能夠執行這個函數,不如說是函數的內存地址()纔是執行這個函數的關鍵。
def func():
    a = 1
    b = 2
    print(a)
    print(a+b)
    return '函數執行結束'

print(func) # <function func at 0x000001FBBA424678>
a = func # 函數名能夠賦值給其餘變量,把函數當成一個變量賦值給另外一個變量
print(a) # <function func at 0x000001FBBA424678>
print(a()) # 函數執行結束
# 經過變量的賦值,變量a,和變量func都指向的這個函數的內存地址,那麼a() 固然能夠執行這個函數了。

函數名能夠當作容器類的元素,其實這個也不難理解,函數名就是一個變量,個人變量是能夠當作容器類類型的元素的:

a = 1
b = 'alex'
c = '武sir'
l1 = [a, b, c]
for i in l1:
    print(i)
'''
# 結果:
1
alex
武sir
'''

那麼函數名也是能夠的:

def func1():
    print("in func1: 嘻嘻")
def func2():
    print("in func2: 哈哈")
def func3():
    print("in func3: 咯咯")
def func4():
    print("in func4: 吱吱")
lst = [func1, func2, func3, func4]
for i in lst:
    i()
# 變量能夠作的,函數名均可以作到,函數名能夠當作函數的參數
def func1():
    print('in func1')

def func2(f):
    print('in func2')
    f()

func2(func1)
# 函數名能夠做爲函數的返回值
def func1():
    print('in func1')

def func2(f):
    print('in func2')
    return f

ret = func2(func1)
ret()  # ret, f, func1 都是指向的func1這個函數的內存地址

小結:函數名是一個特殊的變量,他除了具備變量的功能,還有最主要一個特色就是加上() 就執行,其實他還有一個學名叫第一類對象

(3)格式化輸出(f-strings)

f-strings 是python3.6開始加入標準庫的格式化輸出新的寫法,這個格式化輸出比以前的%s 或者 format 效率高而且更加簡化,很是的好用。相信這個格式化的輸出是你之後惟一的選擇。

f-strings格式化輸出的結構是F(f)+ str的形式,在字符串中想替換的位置用{}展位,與format相似,可是用在字符串後面寫入替換的內容,而他能夠直接識別。

name = 'zhouqian'
age = 18
sex = '男'
msg = F'姓名:{name},性別:{age},年齡:{sex}'
msg1 = f'姓名:{name},年齡:{age},性別:{sex}'
print(msg)
print(msg1)
# 姓名:zhouqian,性別:18,年齡:男
# 姓名:zhouqian,年齡:18,性別:男

他能夠加任意的表達式,很是方便。

print(f'{3*21}')  # 63

name = 'AndreasZhou'
print(f"所有大寫:{name.upper()}")  # 所有大寫:ANDREASZHOU

# 字典也能夠
teacher = {'name': '周乾', 'age': 18}
msg = f"The teacher is {teacher['name']}, aged {teacher['age']}"
print(msg)  # The comedian is 周乾, aged 18

# 列表也行
l1 = ['周乾', 18]
msg = f'姓名:{l1[0]},年齡:{l1[1]}.'
print(msg)  # 姓名:周乾,年齡:18.

# 也能夠插入表達式
def sum_a_b(a,b):
    return a + b
a = 1
b = 2
print('求和的結果爲' + f'{sum_a_b(a,b)}')
# 求和的結果爲3

name = 'zhouqian'
age = 18
ajd = 'handsome'
speaker = f'Hi {name}.'\
          f'You are {age} years old.'\
          f'You are a {ajd} boy!'
print(speaker)
# Hi zhouqian.You are 18 years old.You are a handsome boy!

print(f"{{73}}")  # {73}
print(f"{{{73}}}")  # {73}
print(f"{{{{73}}}}")  # {{73}}
m = 21
# ! , : { } ;這些標點不能出如今{} 這裏面。
# print(f'{;12}')  # 報錯
# 因此使用lambda 表達式會出現一些問題。
# 解決方式:可將lambda嵌套在圓括號裏面解決此問題。
x = 5
print(f'{(lambda x: x*2) (x)}')  # 10

總結:f-string的格式化輸出更加簡潔,方便,易讀。並且他的處理速度對以前的%s 或者format 有了較高的提高,因此之後儘可能使用此種格式化輸出。

(4)匿名函數lambda

匿名函數,顧名思義就是沒有名字的函數,那麼什麼函數沒有名字呢?這個就是咱們之後面試或者工做中常常用匿名函數 lambda,也叫一句話函數。

如今有一個需求:大家寫一個函數,此函數接收兩個int參數,返回和值。

def func(a,b):
    return a+b
print(func(3,4))

那麼接下來咱們用匿名函數完成上面的需求:

func = lambda a,b: a+b
print(func(3, 4))  # 7

咱們分析一下上面的代碼:

語法:

  函數名 = lambda 參數:返回值

1)此函數不是沒有名字,他是有名字的,他的名字就是你給其設置的變量,好比func.

2)lambda 是定義匿名函數的關鍵字,至關於函數的def.

3)lambda 後面直接加形參,形參加多少均可以,只要用逗號隔開就行。

func = lambda a,b,*args,sex= 'alex',c,**kwargs: kwargs
print(func(3, 4,c=666,name='alex'))  # {'name': 'alex'}
# 全部類型的形參均可以加,可是通常使用匿名函數只是加位置參數,其餘的用不到。

4)返回值在冒號以後設置,返回值和正常的函數同樣,能夠是任意數據類型。

5)匿名函數無論多複雜.只能寫一行.且邏輯結束後直接返回數據

接下來作幾個匿名函數的小題:

寫匿名函數:接收一個可切片的數據,返回索引爲0與2的對應的元素(元組形式)。

func = lambda x:(x[0],x[2])
print(func('afafasd'))

寫匿名函數:接收兩個int參數,將較大的數據返回。

func = lambda x,y: x if x > y else y
print(func(3,100))

(5)內置函數

黃色一帶而過:all() any() bytes() callable() chr() complex() divmod() eval() exec() format() frozenset() globals() hash() help() id() input() int() iter() locals() next() oct() ord() pow() repr() round()

all():可迭代對象中,全都是True纔是True。

any():可迭代對象中,有一個True就是True。

# all  可迭代對象中,全都是True纔是True
# any  可迭代對象中,有一個True 就是True
# print(all([1,2,True,0])) # False
# print(any([1,'',0])) # True

bytes:用於不一樣編碼之間的轉化。

# s = '你好'
# bs = s.encode('utf-8')
# print(bs)
# s1 = bs.decode('utf-8')
# print(s1)
# bs = bytes(s,encoding='utf-8')
# print(bs)
# b = '你好'.encode('gbk')
# b1 = b.decode('gbk')
# print(b1.encode('utf-8'))

callable:函數用於檢查一個對象是不是可調用的。若是返回True,object仍然可能調用失敗;但若是返回False,調用對象ojbect絕對不會成功。

name = 'alex'
def func():
    pass
print(callable(name))  # False
print(callable(func))  # True

ord:輸入字符找該字符編碼的位置

chr:輸入位置數字找出其對應的字符

# ord 輸入字符找該字符編碼的位置
# print(ord('a'))
# print(ord('中'))

# chr 輸入位置數字找出其對應的字符
# print(chr(97))
# print(chr(20013))

eval:執行字符串類型的代碼,並返回最終結果。

eval('2 + 2')  # 4
n=81
eval("n + 4")  # 85
eval('print(666)')  # 666

exec:執行字符串類型的代碼。

s = '''
for i in [1,2,3]:
    print(i)
'''
exec(s)

hash:獲取一個對象(可哈希對象:int,str,Bool,tuple)的哈希值。

print(hash(12322))
print(hash('123'))
print(hash('arg'))
print(hash('alex'))
print(hash(True))
print(hash(False))
print(hash((1,2,3)))
'''
-2996001552409009098
-4637515981888139739
1
2528502973977326415
'''

help:函數用於查看函數或模塊用途的詳細說明。

print(help(list))
print(help(str.split))

int:函數用於將一個字符串或數字轉換爲整型。

print(int())  # 0
print(int('12'))  # 12
print(int(3.6))  # 3
print(int('0100',base=2))  # 將2進制的 0100 轉化成十進制。結果爲 4

float:函數用於將整數和字符串轉換成浮點數。

complex:函數用於建立一個值爲 real + imag * j 的複數或者轉化一個字符串或數爲複數。若是第一個參數爲字符串,則不須要指定第二個參數。。

print(float(3))  # 3.0
print(complex(1,2))  # (1+2j)

bin:將十進制轉換成二進制並返回。

oct:將十進制轉化成八進制字符串並返回。

hex:將十進制轉化成十六進制字符串並返回。

print(bin(10),type(bin(10)))  # 0b1010 <class 'str'>
print(oct(10),type(oct(10)))  # 0o12 <class 'str'>
print(hex(10),type(hex(10)))  # 0xa <class 'str'>

divmod:計算除數與被除數的結果,返回一個包含商和餘數的元組(a // b, a % b)。

round:保留浮點數的小數位數,默認保留整數。

pow:求xy次冪。(三個參數爲xy的結果對z取餘)

print(divmod(7,2))  # (3, 1)
print(round(7/3,2))  # 2.33
print(round(7/3))  # 2
print(round(3.32567,3))  # 3.326
print(pow(2,3))  # 兩個參數爲2**3次冪
print(pow(2,3,3))  # 三個參數爲2**3次冪,對3取餘。

repr:返回一個對象的string形式(原形畢露)。

# %r  原封不動的寫出來
# name = 'taibai'
# print('我叫%r'%name)

# repr 原形畢露
print(repr('{"name":"alex"}'))
print('{"name":"alex"}')

紅色重點講解:abs() enumerate() filter() map() max() min() open() range() print() len() list() dict() str() float() reversed() set() sorted() sum() tuple() type() zip() dir()

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(111,222,333,sep='*')  # 111*222*333

print(111,end='')
print(222)  #兩行的結果 111222

f = open('log','w',encoding='utf-8')
print('寫入文件',fle=f,flush=True)

int():pass

str():pass

bool():pass

set(): pass

list() 將一個可迭代對象轉換成列表,pass

tuple() 將一個可迭代對象轉換成元組,pass

dict() 經過相應的方式建立字典,pass

l1 = list('abcd')
print(l1)  # ['a', 'b', 'c', 'd']
tu1 = tuple('abcd')
print(tu1)  # ('a', 'b', 'c', 'd')

abs() 返回絕對值

i = -5
print(abs(i))  # 5

sum() 求和

print(sum([1,2,3]))# 6
print(sum((1,2,3),100))# 106

min() 求最小值

print(min([1,2,3]))  # 返回此序列最小值
ret = min([1,2,-5,],key=abs)  # 按照絕對值的大小,返回此序列最小值
print(ret)
# 加key是能夠加函數名,min自動會獲取傳入函數中的參數的每一個元素,而後經過你設定的返回值比較大小,返回最小的傳入的那個參數。
print(min(1,2,-5,6,-3,key=lambda x:abs(x)))  # 能夠設置不少參數比較大小
dic = {'a':3,'b':2,'c':1}
print(min(dic,key=lambda x:dic[x]))
# x爲dic的key,lambda的返回值(即dic的值進行比較)返回最小的值對應的鍵
# 輸出的結果爲:
# 1
# 1
# 1
# c

max() 最大值與最小值用法相同。

reversed() 將一個序列翻轉, 返回翻轉序列的迭代器 reversed 示例:

l = reversed('你好')  # l 獲取到的是一個生成器
print(list(l))
print('__next__' in dir(l))
ret = reversed([1, 4, 3, 7, 9])
print(list(ret))  # [9, 7, 3, 4, 1]
# 輸出的結果爲:
# ['好', '你']
# True
# [9, 7, 3, 4, 1]

bytes() 把字符串轉換成bytes類型

s = '你好太白'
bs = s.encode('utf-8')
print(bs)
# 結果:b'\xe4\xbd\xa0\xe5\xa5\xbd\xe6\xad\xa6\xe5\xa4\xa7'

s1 = bs.decode('utf-8')
print(s1)
# 結果: 你好太白

s = '你好'
bs = bytes(s,encoding='utf-8')
print(bs)
# 將字符串轉換成字節

bs1 = str(bs,encoding='utf-8')
print(bs1)
# 將字節轉換成字符串

zip() 拉鍊方法。函數用於將可迭代的對象做爲參數,將對象中對應的元素打包成一個個元組,

而後返回由這些元祖組成的內容,若是各個迭代器的元素個數不一致,則按照長度最短的返回,

lst1 = [1,2,3]
lst2 = ['a','b','c','d']
lst3 = (11,12,13,14,15)
for i in zip(lst1,lst2,lst3):
    print(i)
結果:
(1, 'a', 11)
(2, 'b', 12)
(3, 'c', 13) 

sorted排序函數

語法:sorted(iterable,key=None,reverse=False)

iterable : 可迭代對象

key: 排序規則(排序函數),在sorted內部會將可迭代對象中的每個元素傳遞給這個函數的參數.根據函數運算的結果進行排序

reverse :是不是倒敘,True 倒敘 False 正序

lst = [1,3,2,5,4]
lst2 = sorted(lst)
print(lst)    #原列表不會改變
print(lst2)   #返回的新列表是通過排序的
  
lst3 = sorted(lst,reverse=True)
print(lst3)   #倒敘
 
結果:
[1, 3, 2, 5, 4]
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]

字典使用sorted排序

dic = {1:'a',3:'c',2:'b'}
print(sorted(dic))   # 字典排序返回的就是排序後的key
 
結果:
[1,2,3]


和函數組合使用

# 定義一個列表,而後根據一元素的長度排序
lst = ['天龍八部','西遊記','紅樓夢','三國演義']
 
# 計算字符串的長度
def func(s):
    return len(s)
print(sorted(lst,key=func))
 
# 結果:
# ['西遊記', '紅樓夢', '天龍八部', '三國演義']


和lambda組合使用

lst = ['天龍八部','西遊記','紅樓夢','三國演義']
 
print(sorted(lst,key=lambda s:len(s)))
 
結果:
['西遊記', '紅樓夢', '天龍八部', '三國演義']
 
 
lst = [{'id':1,'name':'alex','age':18},
    {'id':2,'name':'wusir','age':17},
    {'id':3,'name':'taibai','age':16},]
 
# 按照年齡對學生信息進行排序
 
print(sorted(lst,key=lambda e:e['age']))
 
結果:
[{'id': 3, 'name': 'taibai', 'age': 16}, {'id': 2, 'name': 'wusir', 'age': 17}, {'id': 1, 'name': 'alex', 'age': 18}]

filter篩選過濾

語法: filter(function,iterable)

function: 用來篩選的函數,在filter中會自動的把iterable中的元素傳遞給function,而後根據function返回的True或者False來判斷是否保留此項數據
iterable:可迭代對象

lst = [{'id':1,'name':'alex','age':18},
        {'id':1,'name':'wusir','age':17},
        {'id':1,'name':'taibai','age':16},]
 
ls = filter(lambda e:e['age'] > 16,lst)
print(list(ls))
 
結果:
[{'id': 1, 'name': 'alex', 'age': 18},
 {'id': 1, 'name': 'wusir', 'age': 17}]

map

映射函數

語法: map(function,iterable) 能夠對可迭代對象中的每個元素進映射,分別取執行function

計算列表中每一個元素的平方,返回新列表

lst = [1,2,3,4,5]
def func(s):
    return  s*s
mp = map(func,lst)
print(mp)
print(list(mp))

改寫成lambda
lst = [1,2,3,4,5]
print(list(map(lambda s:s*s,lst)))

計算兩個列表中相同位置的數據的和
lst1 = [1, 2, 3, 4, 5]
lst2 = [2, 4, 6, 8, 10]
print(list(map(lambda x, y: x+y, lst1, lst2)))
結果:
[3, 6, 9, 12, 15]

imgreduce

from functools import reduce
def func(x,y):
    return x + y

# reduce 的使用方式:
# reduce(函數名,可迭代對象)  # 這兩個參數必須都要有,缺一個不行

ret = reduce(func,[3,4,5,6,7])
print(ret)  # 結果 25
reduce的做用是先把列表中的前倆個元素取出計算出一個值而後臨時保存着,
接下來用這個臨時保存的值和列表中第三個元素進行計算,求出一個新的值將最開始
臨時保存的值覆蓋掉,而後在用這個新的臨時值和列表中第四個元素計算.依次類推

注意:咱們放進去的可迭代對象沒有更改
以上這個例子咱們使用sum就能夠徹底的實現了.我如今有[1,2,3,4]想讓列表中的數變成1234,就要用到reduce了.
普通函數版
from functools import reduce

def func(x,y):

    return x * 10 + y
    # 第一次的時候 x是1 y是2  x乘以10就是10,而後加上y也就是2最終結果是12而後臨時存儲起來了
    # 第二次的時候x是臨時存儲的值12 x乘以10就是 120 而後加上y也就是3最終結果是123臨時存儲起來了
    # 第三次的時候x是臨時存儲的值123 x乘以10就是 1230 而後加上y也就是4最終結果是1234而後返回了

l = reduce(func,[1,2,3,4])
print(l)

匿名函數版
l = reduce(lambda x,y:x*10+y,[1,2,3,4])
print(l)

在Python2.x版本中recude是直接 import就能夠的, Python3.x版本中須要從functools這個包中導入
龜叔本打算將 lambda 和 reduce 都從全局名字空間都移除, 輿論說龜叔不喜歡lambda 和 reduce
最後lambda沒刪除是由於和一我的寫信寫了好多封,進行交流而後把lambda保住了.

藍色將來會講: classmethod() delattr() getattr() hasattr() issubclass() isinstance() object() property() setattr() staticmethod() super()

相關文章
相關標籤/搜索