Day6

ReShaker_發表於2020-10-11

函式也是物件

#Python 中一切皆物件
def print_star(n):
    print("*"*n)
print(print_star)
print(id(print_star))

c =print_star
c(5)

結果:

<function print_star at 0x0000021B716A2F78>
2316890156920
*****

記憶體分析:
在這裡插入圖片描述

變數的作用域(全域性變數和區域性變數)

全域性變數:

  1. 在函式和類定義之外宣告的變數。作用域為定義的模組,從定義位置開始直到模組 結束。
  2. 全域性變數降低了函式的通用性和可讀性。應儘量避免全域性變數的使用。
  3. 全域性變數一般做常量使用。
  4. 函式內要改變全域性變數的值,使用 global 宣告一下

區域性變數:

  1. 在函式體中(包含形式引數)宣告的變數。
  2. 區域性變數的引用比全域性變數快,優先考慮使用。
  3. 如果區域性變數和全域性變數同名,則在函式內隱藏全域性變數,只使用同名的區域性變數

區域性變數和全域性變數效率測試

import math
import time

def test1():
    start = time.time()
    for i in range(10000000):
        math.sqrt(30)
    end = time.time()
    print("耗時:{0}".format(end - start))

def test2():
    b = math.sqrt
    start = time.time()
    for i in range(10000000):
        b(30)
    end = time.time()
    print("耗時:{0}".format(end - start))

test1()
test2()

結果:

耗時:1.387796401977539
耗時:1.003021478652954

淺拷貝和深拷貝

淺拷貝:不拷貝子物件的內容,只是拷貝子物件的引用, 使用copy()方法。
深拷貝:會連子物件的記憶體也全部拷貝一份,對子物件的修改不會影響源物件, 使用deepcopy()方法,


import copy

def testCopy():
    a = [10,20,[30,40]]
    b = copy.copy(a)
    print("a:",a)
    print("b:",b)
    b.append(50)
    b[2].append(60)
    print("淺拷貝測試結果為:")
    print("a:",a)
    print("b:",b)

def testDeepCopy():
    a = [10,20,[30,40]]
    b = copy.deepcopy(a)
    print("a:",a)
    print("b:",b)
    b.append(50)
    b[2].append(60)
    print("深拷貝測試結果為:")
    print("a:",a)
    print("b:",b)
print('**********************************')
testCopy()
print('**********************************')
testDeepCopy()

結果:

**********************************
a: [10, 20, [30, 40]]
b: [10, 20, [30, 40]]
淺拷貝測試結果為:
a: [10, 20, [30, 40, 60]]
b: [10, 20, [30, 40, 60], 50]
**********************************
a: [10, 20, [30, 40]]
b: [10, 20, [30, 40]]
深拷貝測試結果為:
a: [10, 20, [30, 40]]
b: [10, 20, [30, 40, 60], 50]

傳遞不可變物件包含的子物件是可變的情況

#以元組中有列表物件為例
a = (1,3,[5,7])
print("a:",id(a))
def test(m):
    print("m:",id(m))
    m[2][0] = 666
    print(m)
    print("m:",id(m))
    
test(a)
print(a)

結果:

a: 2367543250760
m: 2367543250760
(1, 3, [666, 7])
m: 2367543250760
(1, 3, [666, 7])

函式的可變引數

可變引數指的是“可變數量的引數”。分兩種情況:

  1. *param(一個星號),將多個引數收集到一個“元組”物件中。
  2. **param(兩個星號),將多個引數收集到一個“字典”物件中。
#元組
def f1(a,b,*c):
    print(a,b,c)
f1(1,2,3,4)
#字典
def f2(a,b,**c):
    print(a,b,c)
f2(1,2,name="Yuehai",age=20)

結果:

1 2 (3, 4)
1 2 {'name': 'Yuehai', 'age': 20}

lambda表示式和匿名函式

例:lambda表示式的使用:

f = lambda a,b,c:a+b+c
print(f)
print(f(2,3,4))

結果:

<function <lambda> at 0x0000017F53692F78>
9

eval()函式

功能:將字串 str 當成有效的表示式來求值並返回計算結果。
語法: eval(source[, globals[, locals]]) -> value
引數:
source:一個 Python 表示式或函式 compile()返回的程式碼物件 。
globals:可選。必須是 dictionary。
locals:可選。任意對映物件。

s = "print('abcde')"
eval(s)

遞迴函式

  1. 終止條件 表示遞迴什麼時候結束。一般用於返回值,不再呼叫自己。
  2. 遞迴步驟 把第 n 步的值和第 n-1 步相關聯。

例:使用遞迴計算階乘

def factotial(n):
    if n == 1:
        return 1
    else:
        return n*factotial(n - 1)

for i in range(1,6):
    print(i,"!=",factotial(i))

結果:

1 != 1
2 != 2
3 != 6
4 != 24
5 != 120