掉進懸崖的小白,學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()