Python開發【第五篇】:函數

1. 函數

  函數是組織好的,可重複使用的,用來實現單一,或相關功能的代碼塊。python

  函數分爲 Python 程序內置函數,用戶自定義的函數。將代碼定義爲函數,有以下好處:git

  • 代碼重用(某個特定功能複用)
  • 保持代碼一致性,易維護
  • 可拓展

1.1 定義和調用函數

  使用 def 關鍵字定義一個函數,後面緊跟函數名,小括號也必不可少,語法以下:算法

def func():
    函數體

  函數在執行時,首先將函數體加載到解釋器中,可是不會運行,只有當調用函數後纔會執行,函數名+小括號便可調用函數:express

def func():
    函數體
func()      # 調用函數

1.2 返回值

  有時咱們須要函數返回一些數據來報告執行的結果,全部就須要有返回值,只須要在函數中添加 return 關鍵字,後面跟着返回值便可。編程

def func():
    return 1

  return 將返回值傳遞給函數自己,咱們只要調用函數,再將函數賦值給變量便可得到返回值:json

def func():
    return 1
res = func()        # 得到返回值,並賦值給變量 res
print(res)

1

  返回值能夠是 0 個,也能夠是 1 個 或多個:數組

  • 沒有返回值,返回 None
  • 一個返回值,返回 返回值
  • 多個返回值,返回一個元組
def func():
    # return
    # return 1
    return 1, 2
res = func()
print(res)

None
1
(1, 2)

1.3 函數參數

  函數的參數能夠用函數實現個性化,大體分爲兩類:數據結構

  • 形參:函數在定義時定義的參數
  • 實參:函數在調用時傳入的參數

  形參只有在調用時才分配內存單元,調用結束,就釋放。僅在函數內部有效,不能在函數外部使用。閉包

  實參能夠是常量、變量、表達式、函數,佔用內存空間。app

1.3.1 默認參數

  形參又分爲:默認參數、位置參數、關鍵字參數以及可變長參數,而默認參數即在函數定義時默認賦予某個形參一個值。若函數調用時,不傳入實參,函數使用默認值,不然使用實參。

def func(x=2):      # x 默認爲 2
    return x + 2
res = func()        # 即便不傳入實參函數也能正常運行
print(res)

1.3.2 位置參數和關鍵字參數

  普通的參數即爲位置參數,在調用時實參必須與形參一一對應。而關鍵字參數,能夠不用考慮位置的關係,只須要名字相同便可。

def func(name, words):
    print(name: words)
func('Hello', words='world')    # 第一個爲位置參數,第二個爲關鍵字參數
func(words='World', name='Hello')   # 不用考慮位置

Tips:位置參數必須在關鍵字參數後面

1.3.3 可變長參數

  可變長參數是一種參數組,它能夠是多個參數,只須要在參數前加上星號(*)便可。它能夠增長函數可拓展性,當你不知道定義的函數須要定義幾個參數時,使用它很方便。

  可變長參數分爲:*args 和 **kwargs兩類:

  • *agrs:將參數們收集起來,打包成一個元組,再一一傳遞給函數使用
  • **kwargs:將參數們收集並打包成一個字典

*args

  *args 、**kwargs 是 Python 官方定義的參數名,也能夠是其餘名字,可是最好使用它,以便於辨認。

def func(*args):
    print(args)
    print('有 %d 個參數' % len(args))
    print('第三個參數是:', args[2])
func('P', 'y', 't', 'h', 'o', 'n')
func('Python', 123, '爬蟲')
('P', 'y', 't', 'h', 'o', 'n')
有 6 個參數
第三個參數是: t
('Python', 123, '爬蟲')
有 3 個參數
第三個參數是: 爬蟲

Tips:若是可變長參數後面還有參數,要將其定義爲關鍵字參數,不然會被收集成可變長參數裏面。建議在使用可變長參數時,可將其餘參數設置爲默認參數,或關鍵字參數,這樣不易混淆。

def func(*args, extra=16):
# def func(*args, extra):
    print(args)
    print(extra)
func(1,2,3)
#func(5,6, extra=18)

(1, 2, 3)
16

(5, 6)
18

  星號()既可用來收集打包參數,也能夠用來「解包」參數。當傳入的參數時列表、元組、字典以及集合時,可變長參數將會將其整個打包成只有一個元組的參數,而在其前面添加一個星號( ),就能夠將裏面的元素一個個都解出來。

def func(*args):
    print(args)

l = [1, 2, 3]
t = (4, 5, 6)
d = {'name':'rose', 'age': 18}
func(l)
func(*l)
func(t)
func(*t)
func(d)
func(*d)
([1, 2, 3],)
(1, 2, 3)
((4, 5, 6),)
(4, 5, 6)
({'name': 'rose', 'age': 18},)
('name', 'age')

**kwargs

  另外一種可變長參數就是 **kwargs,它將傳入的實參打包成一個字典,一樣地也支持 「解包」。

def func(x, **kwargs):
    print(x)
    print(kwargs)
    print('總共有 %d 個參數' % len(kwargs))
    print('這些參數分別爲:', kwargs)

func(20, name='rose', age=18)
20
{'name': 'rose', 'age': 18}
總共有 2 個參數
這些參數分別爲: {'name': 'rose', 'age': 18}

  解包,當傳入的參數是字典時:

def func(gender, **kwargs):
    print(gender)
    print(kwargs)
    print('總共有 %d 個參數' % len(kwargs))
    print('這些參數分別爲:', kwargs)

t = {'name': 'rose', 'age': 18}
func('female', **t)
female
{'name': 'rose', 'age': 18}
總共有 2 個參數
這些參數分別爲: {'name': 'rose', 'age': 18}

  當既有 *args,又有 **kwargs,以及位置參數和位置參數時:

def func(gender, country='China', *args, **kwargs):
    print(gender, country)
    print(args)
    print(kwargs)
func('male', 'America', 20, 30, name='rose', age=19)
male America
(20, 30)
{'name': 'rose', 'age': 19}

1.4 函數文檔

  函數文檔即用來描述函數功能的文檔,可讓別人更好地理解你的函數,定義函數文檔是個好的習慣。

def func(x):
    """
    計算一個數加一
    :param x: 
    :return: 
    """
    x += 1
    return x
res = func()

1.5 函數變量

1.5.1 函數和過程

  在 Python 中函數和過程是分開的,函數(function)與過程(procedure)的區別:

  • 函數:有返回值
  • 過程:簡單、特殊且無返回值

  嚴格來講 Python 沒有過程,只有函數,由於即便沒有返回值,也會默認返回一個 None。

def func():
    print('Hi')
res = func()
print(res)

Hi
None

1.5.2 函數變量的做用域

  變量的做用域即變量可見性,也就是可用範圍,通常編程語言分爲:全局變量(global variable)和局部變量(local variable)。

  • 全局變量:程序開始定義時定義的變量,在函數外部,無縮進,做用域爲整個程序
  • 局部變量:在子程序中(通常爲函數)定義的變量,函數內部,有縮進,做用域是整個子程序

當全局變量與局部變量同名是,在子程序中局部變量起做用,在外面全局變量起做用。

# 首先加載整個函數(不執行),調用函數執行函數內部,打印 tom,最後打印 rose
name = 'rose'   # 全局
def test():
    name = 'tom'    # 局部
    print(name)
test()
print(name)

tom
rose

  1. global 關鍵字

  全局變量的做用域是整個程序,函數內部亦可訪問。可是不要在函數內部試圖修改全局變量,這是由於 Python 使用了屏蔽(shadowing)的方式去 保護全局變量。一旦在函數內部修改,則會在函數內部建立一個如出一轍的局部變量。

name = 'rose'
def test():
    name = 'tom'    
    print(name)
test()
print(name)

tom
rose

  從上面例子能夠看出,全局變量的值沒有改變。可是 Python 是支持在函數內部修改全局變量的,只須要在變量前面加上一個 global 關鍵字便可:

name = 'rose'
def test():
    global name
    name = 'tom'
    print(name)
test()
print(name)

tom
tom

總結:當全局與局部變量名字相同時,函數內部優先讀取局部變量。爲了更好地區分全局與局部變量,通常地全局變量名儘可能使用大小,局部變量名使用小寫。

  2. 內嵌函數

  函數支持嵌套,即一個函數中嵌套另一個函數,這種函數叫內嵌函數或內部函數。

name = 'rose'       # (1)
def fun1():         # (2)
    name = 'tom'    # (5)
    def fun2():     # (6)
        name = 'lila'       # (8)
    fun2()          # (7)
    print(name)     # (9)
    
print(name)         # (3)
fun1()              # (4)
print(name)         # (10)

rose
tom
rose

Tips:內部函數只能在內部調用,外部調用會報 NameError

1.5.3 閉包

  閉包(closure)是函數式編程中的一個重要數據結構,Python 中認爲若是在一個內部函數裏,對在外部做用域(但不是全局做用域)的變量進行引用,那麼這個內部函數就是閉包(closure)。

def fun1(x):
    def fun2(y):
        return x * y
    return fun2
a = fun1(6)         # a 接收的是 fun2() 的內存地址
print(a)
b = a(5)            # a(5) 至關於調用 fun2()
print(b)

# 上述能夠簡寫
# res = fun1(6)(5)
# print(res)

<function fun1.<locals>.fun2 at 0x00000000026F48C8>
30

  從上面的例子能夠看出,內部函數 fun2()對外部函數 fun1()的變量 x (不是全局變量)進行了引用,那麼 fun2()便是閉包。

  nonlocal 關鍵字

  但須要注意的是不能在外部函數外面調用內部函數,對外部函數的局部變量只能進行訪問,不能修改。

def fun1():
    name = 'rose'
    def fun2():
        name = 'tom'
        return name
    print(name)
    return fun2
fun1()()

rose        # 外部函數局部變量 name = ‘rose' 並無被修改

  若是在內部函數中想修改外部函數的局部變量能夠用 nonlocal 關鍵字,可是須要注意的是它不能修改全局變量。

def fun1():
    name = 'rose'
    def fun2():
        nonlocal name       # 添加 nonlocal 關鍵字
        name = 'tom'
        return name
    print(name)
    return fun2
fun1()()

tom     # 外部函數局部變量 name = ‘rose' 已經被修改

1.6 函數即變量

  Python 程序按程序執行,遇到函數,先加載到到內存,只有當調用函數時,纔會運行函數體。所以一個函數能夠做爲 變量在另外一個函數內部調用執行,前提是第一個函數須要先加載。

  首先加載 f1()、f2(),再調用 f1(),執行 f1()裏的函數體,最後調用 f2(),執行 f2()裏的函數體:

def f1():           # (1)
    print('from f1')    # (4)
    f2()            # (5)
def f2():           # (2)
    print('from f2')    # (6)
f1()                # (3)

from f1
from f2

  另外一種狀況:

def f2():
    print('from f2')
def f1():
    print('from f1')
    f2()
f1()

from f1
from f2

  第三種狀況,調用 f2()時,由於 函數 f2()還未加載,致使出錯(NameError: name 'f2' is not defined):

def f1():
    print('from f1')
f2()
def f2():
    print('from f2')
f1()

1.7 遞歸函數

  在函數內部,能夠調用其餘函數,若是在調用過程當中直接或間接調用自身,那麼這個函數就是遞歸函數。

  遞歸函數特徵:

  • 必須有明確的結束條件(不然死循環)
  • 每次進入更深一次遞歸時,問題規模比上一次都應有所減小
  • 遞歸效率不高,層次過多容易致使 棧溢出

函數調用是經過棧(stack)實現,每調用一次,棧就會增長一層棧幀,函數返回,則減小一層。因爲棧的大小有限,全部遞歸過多,就會致使棧溢出。

def func(n):
    print(n)
    if int(n/2) == 0:       # 結束條件
        return n
    res = func(int/2)   # 調用自身
    return res
func(10)

10,5,2,1

1.7.1 示例

  遞歸問路

  使用遞歸函數,實現一次遞歸問路操做。

import time
person_list = ['rose', 'tom', 'lila', 'json', 'john']
def ask_way(person_list):
    """
    問路操做
    :param person_list: 被問的人
    :return:
    """
    print('-'*60)
    if len(person_list) == 0:
        return '沒人知道'
    person = person_list.pop()
    if person == 'json':
        return '%s 我知道 xxx 怎麼走,它在 xxx' % person
    print('你好,%s,請問 xxx 在哪裏?' % person)
    print('%s 回答道:我也不知道,我幫你去問問 %s' % (person, person_list))
    time.sleep(2)
    res = ask_way(person_list)
    return res
res = ask_way(person_list)
print(res)
------------------------------------------------------------
你好,john,請問 xxx 在哪裏?
john 回答道:我也不知道,我幫你去問問 ['rose', 'tom', 'lila', 'json']
------------------------------------------------------------
json 我知道 xxx 怎麼走,它在 xxx

  二分查找

data = [1,3,6,7,9,12,14,16,17,18,20,21,22,23,30,32,33,35]
def find_num(data, num):
    """
    使用二分查找法,查找出一個數字的位置
    """
    print(data)
    if len(data) > 1:
        mid = int(len(data)/2)
        if data[mid] == num:
            print('找到數字', data[mid])
        elif data[mid] > num:
            print('要找的數字在 %s 右邊' % data[mid])
            return find_num(data[0:mid], num)
        else:
            print('要找的數字在 %s 左邊' % data[mid])
            return find_num(data[mid+1:], num)
    else:
        if data[0] == num:
            print('找到數字', data[0])
        else:
            print('要找的數字不在列表中')
find_num(data, 66)
[1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]
要找的數字在 18 左邊
[20, 21, 22, 23, 30, 32, 33, 35]
要找的數字在 30 左邊
[32, 33, 35]
要找的數字在 33 左邊
[35]
要找的數字不在列表中

1.7.2 尾調用

  尾調用又稱爲爲遞歸,指的是函數在最後一步調用另外一個函數的過程(最後一行不必定是最後一步)。

# bar 在 foo 內爲尾調用
def bar(n):
    return n
def foo(m):
    return bar(m)
# bar 在 foo 內不是尾調用,最後一步爲 return y
def bar(n):
    return n
def foo(m):
    y = bar(m)
    return y
# bar一、bar2 在 foo 內都是尾調用
def bar1(n):
    return n
def bar2(n):
    return n+1
def foo(x):
    if type(x) is str:
        return bar1(x)
    elif type(x) is int:
        return bar2(x)

  尾調用優化

  定義 a 函數,a 內調用 b,b 調用 c,在內存中造成一個調用記錄,又稱爲調用幀(call frame)。用於存儲調用位置和內部變量等信息,即(a——b——c),直至 c 返回結果給 b,c 的調用記錄消失。b 返回給 a,b 的調用記錄消失,a 返回結果,a 的調用記錄消失,全部記錄都是先進後出,造成一個調用棧(call stack)

1.8 匿名函數

  匿名函數即不須要顯示地指定函數名的函數,Python 容許使用 lambda 關鍵字來建立一個匿名函數,匿名函數也被稱爲 lambda 表達式。

lambda x:x+2
lambda x,y,z:(x+1, y+1, z+1)    # 多個參數

  冒號左邊是原函數參數,能夠有多個參數,逗號分隔便可,冒號右邊爲返回值。對於有些結構比較簡單的函數,能夠直接定義爲匿名函數:

def func(x):
    return x+2
s = func(3)
print(s)

  上述函數可直接定義一個匿名函數:

f = lambda x:x+2
f(3)        # 調用

  匿名函數常與其餘函數搭配使用:

# 將 匿名函數當作參數傳入 calc 中
def calc(func, li):
    ret = []
    for i in li:
        res = func(i)
        ret.append(res)
    return ret
li = [2, 3, 4, 6, 8]
calc(lambda x:x+1, li)

[3, 4, 5, 7, 9]

  lambda 表達式的做用:

  • 執行一些腳本時,省略定義函數過程
  • 對於整個程序只須要執行一兩次的函數,不用考慮命名問題
  • 簡化代碼步驟

2. 函數式編程

2.1 編程論

  當今編程的三種方法論:

  • 面向過程:
  • 函數式編程:特徵(無變量、函數即變量)
  • 面向對象:

  函數式編程(函數+數學函數),更貼近數學,是一種抽象成都很高的編程範式,不容許函數有變量。但 Python 不是嚴格意義上的函數式編程,由於它容許有變量。

  函數式編程特色:

  • 函數即變量(一個函數做爲參數傳入另外一個函數)
  • 返回值是函數(能夠函數自己,也能夠是別的函數)

  函數即變量

def foo(n):
    print(n)
def bar(name):
    print(name)
foo(bar('rose'))

rose
None

  上面例子中,bar('rose') 打印 rose,沒有返回值,所以 foo(bar('rose'))至關於 foo(None)

  返回值是函數

  返回函數自己:

def handle():
    print('from handle')
    return handle       # 返回函數自己內存地址
h = handle()        # 使用變量 h 接收
h()         # 再調用函數自己

from handle
from handle

  返回別的函數:

def test():
    print('from test')
def test1():
    print('from test1')
    return test     # 返回 test 函數的內存地址
n = test1()     # 接收
n()      # 至關於調用 test()

2.2 高階函數

  函數式編程的兩個特徵:函數即變量,返回值是函數,只需知足其中一個條件,便可成爲高階函數。

def add(x, y, f):
    return f(x)+f(y)
print(add(-5, 6, abs))

11

  上面例子中,內置函數 abs 做爲參數傳入函數 add。

2.2.1 map 函數

  map(function, sequence) 函數是高階函數的一種,它有兩個參數:第一個爲函數,另外一個接收一個序列。

  其做用是將序列中每一個元素(for 循環),做爲函數參數傳入第一個參數中,直至序列中每一個元素都被循環,返回一個迭代器對象,用 list 可得到結果。

# 對列表 l 中每一個元素加 1
li = [2, 3, 4, 5, 6]
def add_one(x):
    return x+1
res = map(add_one, li)
print(res)
print(list(res))

<map object at 0x0000000002C5C0B8>
[3, 4, 5, 6, 7]

  上面例子中 map 函數將列表 li 的每一箇中每一個元素取出,再傳入 add_one 中。

  一樣地也可使用 lambda 表達式與 map 函數簡寫:

res = map(lambda x:x+1, li)

  傳入兩個列表:

res = map(lambda x, y: x+y, [1, 3, 5], [2, 4, 6])
print(list(res))

2.2.2 filter 函數

  filter(function or None, iterable)函數有兩個參數:第一個能夠是函數也能夠是 None,第二個爲可迭代對象。

  • 第一個參數爲函數:將序列中每一個元素取出做爲參數,傳入第一個參數中,判斷,並把爲 True 的值返回
  • 第一個參數爲 None:將序列中爲 True 的元素返回

  第一個參數爲函數:

# 過濾掉以 123 結尾的名字
names = ['rose_123', 'lila_123', 'john']
def filter_123(x):
    return not x.endswith('123')        # 返回沒有以 123 結尾的名字
res = filter(filter_123, names)
list(res)

john

  使用 lambda 表達式簡寫:

res = filter(lambda x: not x.endswith('123'), names)
list(res)

  第一個參數爲 None:

res = filter(None, [1, 2, 0, True, False])
list(res)

[1, 2, True]

2.2.3 reduce 函數

  reduce(function, sequence[, initial])函數三個參數:第一個爲函數,第二個爲序列,第三個可選爲初始值。

  Python3 把 reduce 函數集成到 functools 模塊中,所以每次使用時,須要from functools import reduce。它能夠把一個函數做用在一個序列上,這個函數必須接收兩個參數。首先將序列中的前兩個元素取出,傳入函數中,返回值再與序列中接下來的元素作累積計算,直至序列中的每一個元素都被循環。

  求列表中全部元素的乘積:

  常規:

nums = [1, 2, 3, 100]
def reduce_test(func, array):
    res = array.pop(0)
    for i in array:
        res = func(res, i)
    return res
s = reduce_test(lambda x,y: x*y, nums)
print(s)

600

  reduce:

from functools import reduce

nums = [1, 2, 3, 100]
res = reduce(lambda x,y : x*y, nums)
print(res)

600

  首先將 nums 前兩個元素,即 一、2 傳入lambda x,y: x*y中,返回 x*y。再將 3 傳入,最後將 100 傳入,至關於(((1*2)*3)*100)

指定初始值:

from functools import reduce

nums = [1, 2, 3, 100]
res = reduce(lambda x,y : x*y, nums, 6)     # 至關於 (((6*1)*2)*3)*100
print(res)

3600

  累加計算:

from functools import reduce

reduce(lambda x,y: x+y, [1, 2, 3, 4, 5])

15

2.2.4 sorted 函數

  排序算法在程序中是常常用到的算法,不管是冒泡仍是快排,其核心都是比較兩個元素的大小。

  • 數字:直接比較
  • 字符串/字典:須要用函數抽象出來比較

  sorted(iterable, key, reverse)函數也是一個高階函數,在列表內置方法中咱們就已經接觸到了,它能夠對一個列表進行排序,默認從小到大。

sorted([1, -3, 2])

[-3, 1, 2]

  此外,它還接收一個 key 函數來自定義排序,key 函數做用在列表中的每一個元素上,再進行比較,如按絕對值排序:

sorted([1, -3, 2], key=abs)

[1, 2, -3]

  第三個參數 reverse,能夠反向排序:

sorted([1, -3, 2], key=abs, reverse=True)

[-3, 2, 1]

  上面都是針對數字的排序,直接比較其大小便可。可是對於字符串來講,通常地都是比較其首字母在 ASCII 中的大小:

sorted(['b', 'a', 'Z'])     # 由於在 ASCII中 Z<a

['Z', 'a', 'b']

  如今咱們不想按照 ASCII 來排序,而是按照字母表排序,那麼咱們能夠經過指定 key 函數,將全部字符串轉換爲大寫或小寫便可實現:

sorted(['b', 'a', 'Z'], key=str.upper)

['a', 'b', 'Z']

2.2.5 偏函數

  functools 模塊提供了不少功能,其中一個就是偏函數(partial )。

  當函數的參數個數太多,須要簡化時,使用 functools.partial 建立一個偏函數,這個新的函數能夠固定住原函數的部分參數,從而調用更簡單。

語法結構:

from functools import partial

func2 = partial(func, *args, **kwargs)  # 第一個參數:要固定的函數,第二個:原函數的位置參數,第三個:關鍵字參數

  第一個參數能夠是自定義的函數,也能夠是內置函數。

  int() 函數能夠把字符串轉換爲整型,默認按照十進制轉換:

>>> int('123')
123

  int() 函數還額外提供一個 base 參數,若是傳入 base,就能夠作 N 進制轉換:

>>> int('123', base=8)      # 按照八進制轉換
83

內置函數

  假如要轉換大量的二進制字符串,每次都要傳入 base,就會很繁瑣。咱們能夠利用偏函數(partial)將 base=2 固定住,定義一個新的函數,每次只須要傳入要轉換的字符串便可:

>>> from functools import partial

>>> int2 = partial(int, base=2)     # 將 base = 2 固定住
>>> int2('100')     # 至關於 kw={'base': 2}  int('100', **kw)
4

自定義函數

  當咱們調用某個函數,已知某個參數的值時,能夠將其固定住(至關於設定默認值):

from functools import partial

def add(x, y):
    return x % y
add2 = partial(add, 5)  # 自動將 5 做爲 *args 的一部分放在最左邊,也就是 5 % 100
print(add2(100))

# 101

2.2.6 練習

  將列表中年齡小於等於 18 歲的人過濾出來。

people = [
    {'name': 'rose', 'age': 18},
    {'name': 'lila', 'age': 30},
    {'name': 'tom', 'age': 60}
]

res = filter(lambda p: p.get('age') <= 18, people)
print(list(res))

[{'name': 'rose', 'age': 18}]

3. 內置函數

  函數分爲 Python 內置函數和自定義函數,內置函數有不少,可是真正能用到的也比較少。

# abs():求一個數字的絕對值
>>> abs(-5)
5

# all(iterable):判斷序列中全部元素是否爲 True,若是序列爲空,也返回 True,返回布爾值
>>> all([1, 2, 0])
False

# any(iterable):序列中元素 bool(x),只要有一個爲 True,則返回 True,若是序列爲空,返回 False
>>> any([])
False
>>> any(['', 0, 1])
True

# bin(number):十進制轉二進制
>>> bin(10)
'0b1010'

# hex(number):十進制轉十六進制
>>> hex(10)
'0xa'

# bool():轉換爲布爾類型
>>> bool(0)
False
>>> bool(None)
False
>>> bool('')
False

# bytes(obj,encoding=None):將對象編碼(二進制)
# bytes(obj,encoding=None).decode(None):解碼,用什麼編碼就應用什麼解碼
>>> name = '你好'
>>> bytes(name, encoding='utf-8')
b'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> bytes(name, encoding='utf-8').decode('utf-8')
'你好'

# chr(i):返回一個數字在 ASCII 中對應的值
>>> chr(90)
'Z'

# ord(obj):查詢一個字符咋 ASCII 中的對應的數字
>>> ord('Z')
90

# dict():建立一個字典
>>> d = dict()
>>> type(d)
<class 'dict'>

# dir(obj):返回一個對象的全部方法名字
>>> dir(str)

# help(obj):查看幫助文檔
>>> help(list.append)
Help on method_descriptor:

append(...)
    L.append(object) -> None -- append object to end
    
# dirmod(x,y):返回一個元組,結果爲 x/有的商和餘數,通常用做網頁分頁
>>> divmod(10, 3)
(3, 1)

# id(obj):查看一個對象的內存地址
>>> id(10)
1750035808

# globals():查看全局變量
# locals():查看局部變量

# pow(x,y[,z]):冪運算,z 可選, pow(x,y,z)至關於 (x**y)%z
>>> pow(10, 3)
1000
>>> pow(10, 3, 4)
0

# reversed(iterable):反轉一個序列
>>> list(reversed('abc'))
['c', 'b', 'a']
>>> list(reversed([1, 2, 3]))
[3, 2, 1]

# round(number,ndigits):四捨五入,保留幾位有效小數
>>> round(4.5)
4
>>> round(4.564, 2)
4.56

# set(iterable):轉換成集合、建立一個集合
>>> set('123')
{'2', '3', '1'}
>>> s = set()
>>> type(s)
<class 'set'>

# slice(statr,stop[,step]):序列切片/分片
>>> l = 'hello'
>>> s = slice(2, 3)
>>> l[s]
'l'

# str():轉換爲字符串
>>> str(123)
'123'

# sum(iterable, start=0):求序列中全部元素的和,還可指定
>>> l = [1, 2, 3, 4]
>>> sum(l)
10
>>> sum(l, 1)
11

# tuple():轉換爲元組
>>> tuple(['a', 1])
('a', 1)

# vars(obj):返回對象的屬性和屬性值的字典對象。
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'name': '你好', 'd': "{'name:': '
rose'}", 's': slice(2, 3, None), 'p': {'name': 'rose', 'age': 18, 'gender': 'male'}, 't': <zip object at 0x0000000002D9FF08>, 'i': ('c', 3), 'age': {'rose': 18, 'tom': 19}, 'li': 'hello', 'l': [1, 2, 3, 4]}
 >>> vars(str)
 ....
 
 # __import__():當模塊名是字符串是,可使用。
 >>> module_name = 'test'
>>> __import__(module_name)
<module 'test' from 'C:\\Users\\HJ\\Anaconda3\\lib\\test\\__init__.py'>
>>> import module_name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'module_name'

  1. eval()

  eval(expression,[globals[,locals]),用於執行一個字符串表達式,並返回表達式值,能夠去掉字符串的引號

>>> d = "{'name:': 'rose'}"
>>> type(d)
<class 'str'>
>>> s = eval(d)
>>> type(s)
<class 'dict'>

  字符串中表達式的值,也能夠計算:

>>> express = '1*2+3'
>>> eval(express)
5

  2. hash()

  hash(obj)作哈希運算,無論對象有多長,通過哈希運算後的值長度都相同,也不能根據 hash 值反推出原始對象。

  可用於校對軟件/文件是否被別人篡改,還可用於判斷軟件或文件是否下載完整(檢驗官方給出的 hash 值與本身下載完畢 hash 的值是否相同)

  • 可哈希數據類型:即不可變數據類型,如:字符串、元組
  • 不可哈希數據類型:便可變數據類型,如:列表、字典、集合
>>> hash('abc')
5994226220732616244
>>> hash('123')
-3466646395452377901

  3. isinstance()、type()

  兩個都是用於判斷數據類型,官方建議使用 isinstance。

>>> type(123)
<class 'int'>
nums = '123'
if type(nums) is str:
    res = int(nums) + 1

  isinstance(x,A_tuple)有兩個參數:第一個是待肯定類型的數據,第二個是指定一個數據類型,判斷二者是否一致,返回一個布爾值。

>>> isinstance(123, int)
True

  4. zip()

  zip(ite1[,iter2[...]])函數接收兩個序列,要求它們元素數據相等,返回兩個序列元素一一對應的元組(返回的是 zip 對象的內存地址)。

>>> p = {'name': 'rose', 'age': 18, 'gender': 'male'}
>>> t = zip(p.keys(), p.values())
>>> list(t)
[('name', 'rose'), ('age', 18), ('gender', 'male')]
>>> list(zip(['a', 'b', 'c'], [1, 2, 3]))
[('a', 1), ('b', 2), ('c', 3)]

>>> for i in zip(['a', 'b', 'c'], [1, 2, 3]):
...     print(i)
...
('a', 1)
('b', 2)
('c', 3)

  5. max()、min()

  max(iterable, key, default)、min()返回一個序列中的最大、小元素。

  特性:

  • 原理是將序列中每一個元素都循環遍歷出來比較
  • 首先比較第一個字符,分出大小則中止比較,若分出,鑽繼續比較。不一樣數據類型不能比較
  • 字典比較,默認比較 key
>>> max([1, 2, 3])                                       
3                                                        
>>> max(['a', 'b'])                                      
'b'                                                      
>>> max(['a12', 'a2'])                 # a 相同,2>1               
'a2'                                   # b>a                   
>>> max(['a12', 'b10'])                                  
'b10'                                                    
         
>>> age = {'rose': 18, 'tom': 19}      # 字典比較默認比較 key                  
>>> max(age)                                             
'tom'                                          

>>> max(zip(age.values(), age.keys()))        #  既比較大小,又把名字也打印出來                                        
(19, 'tom')

  max()還能夠指定比較方法:

# 取出 age 比較
>>> people = [
    {'name': 'rose', 'age': 18},
    {'name': 'lila', 'age': 30},
    {'name': 'tom', 'age': 60}
]

>>> max(people, key=lambda dic:dic.get('age'))
{'name': 'tom', 'age': 60}
相關文章
相關標籤/搜索