1. 程式人生 > >python內建函式及匿名函式

python內建函式及匿名函式

locals  本地作用域/區域性作用域 會隨著位置的改變而改變
globals 全域性作用域           永遠不變 永遠是全域性

a = 1
b = 2
print(locals())
print(globals())
def func():
    c = 3
    d = 4
    print(locals())
def func2():
    l1 = []
    d1 = {}
    print(locals())     #無論在哪裡列印 得到的都是全域性作用域中的名字
func() func2() # 結果 # {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001CE3C83A470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/PyPractise/day11.py', '__cached__': None, 'a': 1, 'b': 2}
# {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001CE3C83A470>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/PyPractise/day11.py', '__cached__': None, 'a': 1, 'b': 2}
# {'d': 4, 'c': 3} # {'d1': {}, 'l1': []}

range(起始位置,終止位置,步長)
range(終止位置)
range(起始,終止位置)

range(5)  # 0,1,2,3,4
range(5, 0, -1)  # 5,4,3,2,1
range(1, 10, 2)  # 1,3,5,7,9

print(要列印的內容1,要列印的內容2,sep = '分隔符',end = '結束符',file=file.txt, flush=False)
file:  預設是輸出到螢幕,如果設定為檔案控制代碼,輸出到檔案
sep:   列印多個值之間的分隔符,預設為空格
end:   每一次列印的結尾,預設為換行符
flush: 立即把內容輸出到流檔案,不作快取(預設快取)
#print的本質,就是寫檔案,這個檔案是pycharm的螢幕

print(123,'abc',sep='|',end='@')
print('www')
結果:
123|[email protected]

事例二
f = open('file','w')
print(123,'abc',file=f,flush=True)
f.close()

案例:列印進度條
import time   #匯入別人寫好的程式碼
def func():
    for i in range(0,101,2):
        time.sleep(0.1)     #每一次在這個地方阻塞0.1s
        char_num = i//2     #控制輸出長度
        if i == 100:
            per_str = '\r%s%% : %s\n' % (i, '*' * char_num)     # %% 轉義%,\n換行符
        else:
            per_str = '\r%s%% : %s' % (i, '*' * char_num)
        print(per_str,end = '')     #per_str,end = ''格式化輸出去除print末尾的預設換行符\n,不換行列印
func()
print('下載完成')

callable() 判斷某一個變數是否可呼叫(True/False)

def call(arg):
    if callable(arg):
        arg()
    else:
        print('引數不符合規定')
def func():
    print('in func')
    return 1
func2 = 1234
call(func)
call(func2)
print(callable(func))
print(callable(func2))
結果
in func
引數不符合規定
True
False

round(小數,保留幾位小數)  小數精確
整數是奇數 -> 正常四捨五入
整數是偶數 -> 五舍六入

2.x(完全的四捨五入)和3.x(更精準的計算方式)不同
print(round(2.3258358))
print(round(2.3253358,2))
print(round(2.3254358,3))
print(round(1.5))
print(round(2.5))
print(round(2.6))
結果
2
2.33
2.325
2
2
3

pow(x,y,z=1) 冪運算/冪餘運算 x的y次方%z

print(pow(2,3))
print(pow(3,2))
print(pow(5,3,2))
print(pow(4,2,2))
print(pow(4,3,2))
結果
8
9
1
0
0

list
tuple

reversed  返回一個迭代器,節省記憶體
reversed 不修改原基礎: 不直接返回列表而返回迭代器,為了不佔用更多的記憶體
reverse 是在原基礎上修改: 2000項的列表,不會產生額外的記憶體佔用

l = [1,2]
l.reverse()
print(l)
結果:
[2, 1]

ret = reversed([1,2,3])  # iterator可迭代的
print(ret)
print(list(ret))
結果:
<list_reverseiterator object at 0x0000024B9ECEEC88>
[3, 2, 1]

lst = ["河南", "四川", "東北", "山東", "上海"]
r = reversed(lst)
print(list(r))
結果
['上海', '山東', '東北', '四川', '河南']

s= "不是上海自來水來自海上"
print(s[::-1])
it = reversed(s)
s2 = ''
for i in it:
    s2 += i
print(s2)
結果:
上海自來水來自海上是不
上海自來水來自海上是不

slice  切片

l = [1,2,3,4,5,]
ret = slice(1,4)   # [1:4]
print(l[ret])
等於
print(l[1:4])
結果:
[2, 3, 4]
[2, 3, 4]

format(填充)

print(format('test', '<20'),'alex')
print(format('test', '>20'),'alex')
print(format('test', '^20'),'alex')
結果:
test                 alex
                test alex
        test         alex

進位制轉換
print(format(3, 'b'))   # 轉換成二進位制  binary  0b11
print(format(65, 'c'))  # 轉換成unicode字元  ascii
print(format(11, 'o'))  # 轉換成八進位制  0o    13
print(format(11, 'x'))  # 轉換成十六進位制(小寫字母)
print(format(11, 'X'))  # 轉換成十六進位制(大寫字母)
print(format(11, 'd'))  # 轉換成十進位制
print(format(11, 'n'))  # 和d一樣
print(format(11))       # 和d一樣
結果
11
A
13
b
B
11
11
11

科學計數法
print(format(123456789, 'e'))   # 科學計數法,預設保留6位小數,表示大的資料
print(format(123456789, '.2e')) # 科學計數法,保留2位小數(小寫)
print(format(123456789, '0.2E'))# 科學計數法,保留2位小數(大寫)
結果
1.234568e+08
1.23e+08
1.23E+08

浮點計數法
print(format(1.23456789, 'f'))    # 浮點數計數法,保留6位小數
print(format(1.23456789, '0.2f')) # 小浮點數計數法,保留2位小數
print(format(1, '0.10f'))         # 小浮點數計數法,保留10位小數
print(format(1.23456789e+10000, 'F')) # 小浮點數計數法
結果
1.234568
1.23
1.0000000000
INF        #無窮大

repr() 還原字串最官方的效果

轉義字元
\n 換行
\t tab 製表符
\r 回車
\"   雙引號
\'  單引號
\\    \
print('hello\\n world')
結果
hello\n world

還原字串最官方的效果
print(repr('hello\\n world'))
結果
'hello\\n world'

原封不動的顯示字串
print(r'hello\\n wo\trld')
結果
hello\\n wo\trld

zip 拉鍊函式,返回迭代器-節省記憶體,水桶效應

a = (1,2,3,4)
b = ('a','b','c')
c = ['111','222']
d = {'k1':'v1','k2':'v2'}
ret = zip(a,b,c,d)
print(ret)

for i in ret:
    print(i)
結果:
<zip object at 0x0000023ECB077108>
(1, 'a', '111', 'k1')
(2, 'b', '222', 'k2')

匿名函式
定義
匿名函式的記憶體地址 = lambda 引數1,引數2 : 返回值/返回值的表示式
呼叫
接收返回值 = 匿名函式的記憶體地址(引數)

def定義的函式: 都是有名字的,def後面寫的就是函式名
def qqxing():
    print('qqxing')
func = qqxing
func2 = qqxing
print(qqxing.__name__)
print(func.__name__)    #內建屬性,通過執行的函式名返回定義的函式名
print(func2.__name__)
結果
qqxing
qqxing
qqxing

事例2
def exe(func):
    func()
    print('執行%s函數了'%func.__name__)
def qqxing():
    print('qqxing')
def wahaha():
    print('wahaha')
exe(wahaha)
exe(qqxing)
結果
wahaha
執行wahaha函數了
qqxing
執行qqxing函數了


匿名函式沒有名字,統一的名字是:<lambda>,別稱: lambda表示式
定義一個很簡單的函式,複雜的函式不要用lambda
def func(a,b):
    return a + b
ret = func(1,2)
print(ret)

fn = lambda a,b:a + b
ret = fn(5,6)
print(ret)
print(fn)
結果
3
11
<function <lambda> at 0x0000027766AD98C8>
使用場景: 配合著sorted,map,filter一起使用

事例2
qqxing = lambda n:n**2
print(qqxing.__name__)
ret = qqxing(8)
print(ret)
結果
<lambda>
64

事例3
f = lambda *args:sum(args)
ret = f(1,2,3)
print(ret)
執行結果
6

事例4
dic = {'k1':10,'k2':100,'k3':30}
m = max(dic,key=lambda k:dic[k])
print(m)
同等
def func(k):
    return dic[k]
m = max(dic,key=func)
print(m)
結果
k2

接收兩個引數,返回較大值(不用max內建函式)
f1 = lambda a,b : max(a,b)
f2 = lambda a,b : a if a>b else b

sorted() 排序,根據key對應的函式的返回值的大小來排序的
由於必須要知道後面的值是誰,才能排出順序,所以結果就是排序後的結果而不是可迭代的
按照字串長度排序
執行流程: 把可迭代物件中的每一項拿出來, 作為引數傳遞給後面key函式,函式返回數字,根據數字進行排序

lst = ['關穀神奇','呂小布','諾蘭','山口美惠子','']
def func(s):
    return len(s)
ret = sorted(lst,key=func)
print(ret)
同等
print(sorted(lst,key=lambda s:len(s)))
結果:
['', '諾蘭', '呂小布', '關穀神奇', '山口美惠子']

事例2
lst = [
    {"name":"bob", "shengao":150, "tizhong":250},
    {"name":"jary", "shengao":158, "tizhong":150},
    {"name":"jack", "shengao":177, "tizhong":130},
    {"name":"pique", "shengao":165, "tizhong":130},
    {"name":"alice", "shengao":160, "tizhong":120},
    {"name":"athena", "shengao":183, "tizhong":190}
]
按照體重進行排序
按照身高進行排序
print(sorted(lst,key=lambda dic:dic['tizhong']))
print(sorted(lst,key=lambda dic:dic['shengao']))


事例3
l = [-3,1,2]
l.sort()
print(l)
def func(n):
    return abs(n)
l.sort(key = func)
print(l)
結果
[-3, 1, 2]
[1, 2, -3]

事例4
l = [1,-3,2]
new_l = sorted(l)   #在不改變原列表的情況下 生成一個新列表
print(l)
print(new_l)
def func(n):
    return abs(n)
ret = sorted(l,key = func)
print(ret)
結果
[1, -3, 2]
[-3, 1, 2]
[1, 2, -3]

事例5
按照每一個字典中商品的價格從高到低排列
l = [{'name':'電腦','price':1999},{'name':'滑鼠','price':2000}]
def func(dic):
    return dic['price']
l.sort(key=func,reverse=True)
print(l)
同等
new_l = sorted(l,key = func,reverse= True)
print(new_l)
結果:
[{'name': '滑鼠', 'price': 2000}, {'name': '電腦', 'price': 1999}]

filter 篩選

過濾掉名字結尾帶剛字的人
把可迭代物件開啟,把內部元素一個一個的傳遞給前面的函式,由這個函式決定此項是否保留
lst = ['旭日陽剛','金毛獅王','李剛','張傑']
f = filter(lambda name:not name.endswith(''),lst)
print(f)
print(list(f))
結果:
<filter object at 0x00000206FCB37208>   #可迭代物件
['金毛獅王', '張傑']

事例2
lst = [
    {"name":"bob", "shengao":150, "tizhong":250},
    {"name":"jary", "shengao":158, "tizhong":150},
    {"name":"jack", "shengao":177, "tizhong":130},
    {"name":"pique", "shengao":165, "tizhong":130},
    {"name":"alice", "shengao":160, "tizhong":120},
    {"name":"athena", "shengao":183, "tizhong":190}
]
ret = filter(lambda a:a['tizhong'] < 180,lst)
print(list(ret))
結果:
[{'name': 'jary', 'shengao': 158, 'tizhong': 150}, {'name': 'jack', 'shengao': 177, 'tizhong': 130}, {'name': 'pique', 'shengao': 165, 'tizhong': 130}, {'name': 'alice', 'shengao': 160, 'tizhong': 120}]

事例3
ret = filter(None,[1,2,3,0,False])  #只保留真的
print(ret)
for i in ret:
    print(i)
結果:
<filter object at 0x000002BD91BCEBA8>
1
2
3

事例4
def func(i):
    if i % 2 != 0:
        return True
l = [1, 4, 6, 7, 9, 12, 17]
for i in filter(func,l):  # 迭代l,每一個元素作為引數傳給func,如果func的返回值為True,那麼l中的這個元素就保留
    print(i)
結果:
1
7
9
17

事例5
def func(i):
    if type(i) is not dict:     #判斷i型別不是dict的就返回True
        return True
同等
def func(i):
    return type(i) is not dict

l = ['sjkdhf',[1,2,3],{},()]    #去掉列表中的字典,用filter
ret = filter(func,l)
print(list(ret))
結果:
    ['sjkdhf', [1, 2, 3], ()]

# filter 就像 帶著if條件的列表推導式
    l = ['sjkdhf',[1,2,3],{},()]
    print([i for i in l if type(i) is not dict])

map 對映函式
一個迭代器中的每一個元素都需要去做同一個操作並返回一個結果組成一個新列表的時候map來處理

lst = ['關穀神奇','呂小布','諾蘭','山口美惠子','']
m = map(lambda s:'姓名:'+s,lst)
print(m)
for i in m:
    print(i)
結果:
<map object at 0x000001B76BAA7208>
姓名:關穀神奇
姓名:呂小布
姓名:諾蘭
姓名:山口美惠子
姓名:易

事例2
列表中的每一個值的平方組成的新列表
lst = [1,5,78,12,16]
m = map(lambda i:i**2,lst)
print(list(m))
同等
print([i**2 for i in lst])
同等
lst = [1,5,78,12,16]
def func(num):
    return num**2
ret = map(func,lst)
print(list(ret))
結果:
[1, 25, 6084, 144, 256]

事例3
def func(i):
    return i*'*'
ret = map(func,[1,2,3])
print(ret)
for i in ret:
    print(i)
結果:
<map object at 0x0000024AEBB4ECC0>
*
**
***

eval() 有返回值,可以將字串資料型別的python程式碼執行,通過拼接字串的方式來執行不同的程式碼--簡化程式碼
eval\exec這個函式,不能直接操作檔案當中讀進來的,從網路上傳進來,使用者輸入的

eval('print(1+2+3+4)')  #返回10
ret = eval('1+2/3*4')
print(ret)              #有返回值
結果:
10
3.6666666666666665

事例2
code = input("請輸入你要執行的程式碼:")
ret = eval(code)
print(ret)

事例3
把字串型別的程式碼還原回字典, 列表, 元組
s = "{'name':'bob', 'age':18, 'isMan':False}"   #字串
ret = eval(s)   #側重的有返回值
print(ret)
print(type(ret))
結果:
{'name': 'bob', 'age': 18, 'isMan': False}
<class 'dict'>

事例4
with open('測試檔案.txt','r',encoding='utf=8')as f:
    content=f.read()
    print(content,type(content))
    print(eval(content),type(eval(content)))
    print(eval(content)[0])
結果:
[{'id':1},{'name':'alex'}] <class 'str'>
[{'id': 1}, {'name': 'alex'}] <class 'list'>
{'id': 1}

將普通字串'<'轉換成<小於
def func(f):
    if eval('33 %s 20'%f):
        print('符合條件')
    else:
        print('不符合條件')
if '>':
    func('>')
if '<':
    func('<')

exec() 沒有返回值,執行字串型別的程式碼,不能太長,不能太亂

code = input("請輸入你要執行的程式碼")
exec(code)  # 沒有返回值. 想要返回值用eval
print(a)    # pycharm報錯不一定準
結果:
請輸入你要執行的程式碼a=3+4+9
16

事例2
exec('print(1+2+3+4)')  # 沒有返回值,想要返回值用eval
ret = exec('1+2/3*4')
print(ret)              #沒有返回值None
exec('for i in range(3):print(i)')
執行結果
10
None
0
1
2

compile編譯  
把要執行的程式碼先預編譯,能夠節省時間工具,通過exec和eval可以執行我們的程式碼
引數說明:
resource 要執行的程式碼,動態程式碼⽚片段
檔名,程式碼存放的檔名,當傳入了第一個引數的時候,這個引數給空就可以了
模式,取值有3個
    exec: 一般放一些流程語句句的時候
    eval: resource只存放一個求值表示式.
    single: resource存放的程式碼有互動的時候,mode應為single

先編譯 python -編譯-> 位元組碼(bytes) -解釋-> 機器碼 0101010100101
先整體編譯
code1 = 'for i in range(0,3): print (i)'   #這是一個字串程式碼

事例1
流程語句使用exec
compile1 = compile(code1,'','exec')     #預編譯 python-> 位元組碼
exec (compile1)  #解釋
exec (compile1)
exec(code1)     #編譯+解釋
結果:
0
1
2
0
1
2
0
1
2

事例2
簡單求值表示式用eval
code2 = '1 + 2 + 3 + 4'
compile2 = compile(code2,'','eval')
print(eval(compile2))
結果:
10

事例3
互動語句用single
code3 = 'name = input("please input your name:")'
compile3 = compile(code3,'','single')
exec(compile3)
print(name)
結果:
please input your name:linux
linux