掉進懸崖的小白,學python時被拉進函數漩渦,參數類型灌入腦中,學會複用代碼 DRY,局部變量和全局變量的衝突解決。猜數遊戲,數字轉換大寫漢字,隨機賦不重複值。

掉進懸崖的小白,學python時被拉進函數漩渦,參數類型灌入腦中,學會複用代碼 DRY,局部變量和全局變量的衝突解決。猜數遊戲,數字轉換大寫漢字,隨機賦不重複值。

函數(function)

函數論:

廣義:
爲獲得某種東西或達到某種目的而採取的手段與行爲方式。

狹義:
函數是指由一系列的程序語句組成的代碼塊

特性:

1.帶名字的代碼段
2.函數是代碼重複使用的重要手段,是重用的基本手段:
無論現實世界還是程序世界,都以函數來達到重用的目的

定義函數

定義語法:[]表示可選 <>表示必備
<函數名>([參數列表])<:>
# 待執行語句
# 如果有需要顯式返回<return 標識符>或
用縮進塊來表示函數體,是函數的管轄區塊

函數可以出現的位置:
模塊(moudle)、類(class)、函數(function)中

命名規範:
函數名、參數名全部小寫,多語義用_連接,函數名、參數名要儘量有意義。

調用函數

函數的目的在於重用,所有的函數編寫完成後,都處於等待調用狀態,被調用後函數開始執行,直到函數返回(有無返回值均必須返回)

函數大多數會在其他函數內部或模塊內被調用
注意:模塊內調用時注意只能調用該行語句之前出現過的函數
原因:代碼自上向下執行

調用的規則:

1.調用者和被調用者相互可見
採用直接調用的方式
示例:
def func1():
print(“函數1”)
pass

func1() # 調用函數func1

2.調用者和被調用者相互不可見
先import模塊再調用:注意調用時帶上模塊.
示例:
be_call_functions.py:
def be_call():
return “test” # 此處返回
call_functions.py:
import be_call_functions

be_call_functions.be_call()

3.特殊的調用方式
析構函數等魔法函數需要用特殊的方案調用
例如:
析構函數由系統自行調用等等
後續會逐步學到

返回值類型:

所有函數都需要返回
只是沒寫return的會自動返回None
函數有無返回值取決於函數的調用者是否需要返回值
注意:
函數遇到return立即退出並返回 so也常作爲控制方法結束的手段
思考:瞭解
若返回值數量超過1個怎麼辦?
默認多返回:return a, b, c, d…
或者使用列表等其他容器返回
一般這樣接收結果:
ret1, ret2, ret3 = func_return()

參數

參數分爲兩種類型:

形式參數:由函數編寫者在預定義時限定
實際參數:任意的數據類型(爲形參賦值)在函數的調用者中定義賦值,在實際調用(使用)函數的時候 傳入函數的參數

聲明和傳參:
形式參數:
def area(radius): # radius即爲形式參數
return 3.14*radius**2

實際參數:
r = 5
print(area®) # r即爲實際參數

// 傳參的實質:用實際參數爲形式參數賦值
radius = r

位置參數:固定位置的參數

def func_args(arg1, arg2, arg3):
print(arg1, arg2, arg3)
調用時傳實參時按位置傳遞:
func_args(1, 2, 3)
結果:1 2 3
也可以:
func_args(arg3=3, arg1=1, arg2=2)

默認參數:可以爲參數設定默認值 調用時可以選擇使用默認值而不傳實參

def func_args(arg1=1, arg2=2, arg3=3):
print(arg1, arg2, arg3)
調用時傳實參:
func_args()
結果:1 2 3
也可以:
func_args(3, 2, 1)
func_args(arg3=6, arg1=6, arg2=6)

命名關鍵字參數:*

以後的參數全部爲顯式命名傳參的參數
注意:命名關鍵字參數和可變參數不能同時出現
def func_args(
, arg1, arg2, arg3):
print(arg1, arg2, arg3)
調用時傳實參:必須顯式命名傳參
func_args(arg3=6, arg1=6, arg2=6)

可變參數:*args

可以選擇傳遞0-n個參數
注意:可變參數無法和命名關鍵字參數同時出現
def func_args(*args):
for i in range(len(args)):
pri nt(args[i])
調用時傳實參:
func_args()
func_args(1)
func_args(1, 2)
func_args(1, 2, 3…,n)

參數的傳遞

參數傳遞需要明白的要點:
形參的修正對實參的影響程度

參數傳遞的方式:
形式參數 = 實際參數

傳參規則:
根據形式參數類型的不同 對實際參數的影響B程度也不相同
A:不可變類型:字符串、數字、布爾、元組
B:列表、類、對象、集合、字典

函數內部形參修正對函數外實參的影響程度:
A:不影響實際參數(同上述A:不可變類型)
B:影響實際參數(同上述B:可變類型)

不可變類型傳參:形參的修改不會傳遞給實參 推薦

def swap(x,y):
x, y = y, x # 形參x,形參y交換數據

x = 666 # 實參x 都叫x,但意義不同
y = 888 # 實參y 都叫y,但意義不同
swap(x, y) #參數傳遞 形參x = 實參x 形參y = 實參y
print(“實參x =”, x, “實參y=”, y)
結果:實參x = 666 實參y= 888

可變類型傳參:形參的修正會傳遞給實參

def change_list(arg_list):
arg_list[1] = 666

my_list = [1, 2, 3, 4]
change_list(my_list)
print(my_list)
結果:[1, 666, 3, 4]

局部變量:

在函數內部聲明並使用的數據量,隨函數的啓動而出生,隨函數的退出而消亡
作用域在函數內
def fun(x):
y= 2
print( “乘法的運行結果:” , x * y)
print( “y的值是:”, y)
報錯的原因是因爲試圖訪問局部變量,但是訪問的地方不在該變量y的作用域中

全局變量

在模塊中直接聲明使用的數據量,整個模塊中可以使用
作用域在模塊內
g_num=“我屬於模塊 在模塊內的任意地方都可使用”
def visitor_g1():
print(g_num)

def visitor_g2():
print(g_num)

visitor_g1()
visitor_g2()
print(g_num)

衝突場景

1.函數內修改全局變量會被解釋器認爲新聲明瞭一個局部變量

例:
num = 10

def set_num(in_num):
num = in_num
pass

set_num(111)
print(num)
結果:10

解決辦法:global關鍵字
num = 10

def set_num(in_num):
global num
num = in_num
pass

set_num(111)
print(num)
結果:111

2.在函數內新聲明的局部變量和全局變量同名,但是又想使用全局變量
discount = 0.9 # 全場9折

def pay(money):
discount = 0.8 # 折上折
print(“請pay:”, money * discount * discount)
pass

pay(10000)
結果:請pay: 6400.0

解決辦法:globals()函數
discount = 0.9 # 全場9折

def pay(money):
discount = 0.8 # 折上折
print(“請pay:”, money * globals()[“discount”] * discount)
pass

pay(10000)
結果:請pay: 7200.0

有趣練習題

##持續獲取用戶輸入,直到用戶輸入的字符串中既有字母又有數字。

def task5():
    while 1:
        str1 = input("輸入一個既有字母又有數字的消息:")
        # 做檢測
        is_have_char = False
        is_have_num = False
        for i in range(len(str1)):
            if "0" <= str1[i] <= "9":
                is_have_num = True
            if "A" <= str1[i] <= "Z" or "a" <= str1[i] <= "z":
                is_have_char = True
            # 爲了性能 提前中斷
            if is_have_char and is_have_num:
                break
        else:
            continue
        break
    return str1


# print(task5())

有一個長度爲62的字符列表,請爲這個列表隨機賦值(a-z A-Z 0-9)要求每個下標位置的字符都不重複。

def task6():
    chars = []
    while len(chars) != 62:
        # 隨機出62個字符當中的一個
        # ord(字符)可以得到該字符的數字表示
        random_char_num = random.randint(ord("0"), ord("z"))
        # 48-57 65-90 97-122
        if ord("9") < random_char_num < ord("A") or ord("Z") < random_char_num < ord("a"):
            continue
        # chr(數字)->字符
        char = chr(random_char_num)
        if char not in chars:
            chars.append(char)
    return chars


# print(task6())

寫一個函數將整型數字(int 不含0)轉換爲漢字大寫格式。例:111=>壹佰壹拾壹

說明:

# 167891111
# 使用列表:
# 漢字列表:["零","壹","貳","叄","肆","伍","陸","柒","捌","玖"]
#            0    1    2    3    。。。。                 9
# "167891111"=>"1"->漢字[int("1")]
# 單位:["圓", "拾", "佰", "仟", "萬", "拾", "佰", "仟", "億", "拾", "佰", "仟", "萬"]
#        0    1    2     3   4    5    6    7.....
# "167891111"
#  012345678
#  876543210:len-1-i:單位[len-1-i]

解題:

def task7(num):
    # 做數字位數的限定
    if len(str(num)) > 13:
        print("暫時不支持13位以上的轉換!")
        return
    # 準備漢字和單位列表
    zhs = ["零", "壹", "貳", "叄", "肆", "伍", "陸", "柒", "捌", "玖"]
    units = ["圓", "拾", "佰", "仟", "萬", "拾", "佰", "仟", "億", "拾", "佰", "仟", "萬"]
    # 設定轉換後的字符串
    ret = ""
    num_str = str(num)
    for i in range(len(num_str)):
        ch = num_str[i]
        ret += zhs[int(ch)] + units[len(num_str) - 1 - i]
    return ret


# print(task7(123456789))

隨機賦值,不重複操作

# 14.使用Random類給一個列表的所有元素賦隨機初值(不重複)。
def task14():
    # 爲10個位置的列表找到10個各不相同的隨機數(1-10)
    # 爲每一個位置找不重複的隨機數
    # 定義一個列表
    # nums = [0] * 10
    # for i in range(len(nums)):
    #     while 1:
    #         # 爲i位置找到和之前位置不同的隨機數
    #         random_num = random.randint(1,10)
    #         if random_num not in nums:
    #             nums[i] = random_num
    #             break
    # nums = []
    # while len(nums) != 10:
    #     random_num = random.randint(1, 10)
    #     if random_num not in nums:
    #         nums.append(random_num)
    # return nums

    # 爲數字找隨機位置:洗牌算法
    # nums = [0] * 10
    # for i in range(1, 11):
    #     while 1:
    #         # i:1-10
    #         # 隨機位置
    #         random_index = random.randint(0, len(nums) - 1)
    #         # 找到了一個隨機位置
    #         # 判斷該位置是否已經有數字了
    #         if nums[random_index] == 0:
    #             nums[random_index] = i
    #             break

    # 使用隨機打亂方式獲取不重複數據
    nums = list(range(1, 11))
    random.shuffle(nums)
    return nums


# print(task14())

猜數遊戲

# 23.猜數遊戲
# 1.隨機出現一個數(範圍自定義) 作爲答案
# 2.提示用戶輸入並根據答案和用戶輸入的大小關係輸出大了? 小了?
# 3.5次機會
# 4.可以重複玩
# 5.根據猜對的次數進行評價
# 6.無論對錯 請告知答案
#
def repeat_play():  # 定義重複玩函數
    while True:
        guess_nums()
        an = input("是否退出遊戲?(y/n)")
        if an == "y":
            return False


def guess_nums():  # 猜數遊戲
    i = 0
    game_answer = random.randint(0, 100)
    while i < 5:
        user_answer = in_int()
        # print(game_answer)
        i += 1
        if user_answer == game_answer:
            break
        print(f"第{i}次你猜{user_answer}大了") if user_answer > game_answer else print(f"第{i}次你猜{user_answer}小了")
    print(f"本輪隨機答案爲:{game_answer}")
    print(f"{i}次猜對,歐皇附體!") if i == 0 else print(f"{i}次猜對,運氣真好!") \
        if i == 1 else print(f"{i}次猜對,猜的不錯!") if 4 > i > 1 else print(f"{i}次猜對,太及時了!") \
        if i == 4 else print("本次遊戲未猜中,繼續努力!")


# guess_nums()
# repeat_play()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章