前言
從今天開始,我就不用“學習之路”這個標題了,感覺突出不了重點,都沒啥人看啊!前面我們已經學習了Python的基礎語法,瞭解了Python的分支結構,也就是選擇結構、循環結構以及函數這些具體的框架,還學習了列表、元組、字典、字符串這些Python中特有的數據結構,還用這些語法完成了一個簡單的名片管理系統。下面我就將介紹一下Python的一些進階語法規則,爲後面更復雜的編程打下基礎。
引用
引用這個名詞相信學過C語言和C++指針的同學應該有點印象,引用和指針還是一個很容易被混淆的概念。簡單來說,引用是一個變量,是另外一個你想被引用的變量的別名,就像是你給某個人起的一個外號,你用這個外號來代替他的名字來稱呼他,類似於一個副本。在Python中,變量和數據是分開存儲的,數據保存在內存中的一個位置,變量中保存數據在內存中的地址。變量中記錄數據的地址,就叫做引用。下面是在終端中運行ipython這個Python的交互式窗口,其中id()函數是返回對象的內存地址。
a = 1實際上就是將a這個標籤貼在1上,b = a同樣也是把b這個標籤貼在1上,所以b和a都是1的引用,當a = 2時,a這個標籤就會貼在2上,然而b不會因爲b = a這個語句發生變化,其任然是1的引用。
def test(num):
print("在函數內部 %d 對應的內存地址是 %d " % (num, id(num)))
# 1.定義一個字符串變量
result = "hello"
print("函數要返回數據的內存地址是 %d " % id(result))
# 2.將字符串變量返回,返回的是數據的引用,而不是數據本身
return result
# 1.定義一個數字的變量
a = 10
# 數據的地址本質上就是一個數字
print("a 變量保存數據的內存地址是 %d" % id(a))
# 2.調用test函數,本質上傳遞的是實參保存數據的引用,而不是實參保存的數據
# 注意:如果函數有返回值,但是沒有定義變量接收
# 程序不會報錯,但是無法獲得返回結果
r = test(a)
print("%s 的內存地址是 %d" % (r,id(r)))
# 輸出結果
a 變量保存數據的內存地址是 10914784
在函數內部 10 對應的內存地址是 10914784
函數要返回數據的內存地址是 139989701883752
hello 的內存地址是 139989701883752
局部變量和全局變量
簡而言之,局部變量就是在函數內部定義的變量,只能在函數內部使用(後面會學類,在類內部使用),在函數外部不可被發現,不可被使用。全局變量就是定義在模塊內,在所有的函數、類的外面。
局部變量:
def demo1():
# 定義一個局部變量
# 1.出生:執行了下方的代碼之後,纔會被創建
# 2.死亡:函數執行完成之後
num = 10
print("在demo1函數內部的變量是 %d" % num)
def demo2():
num = 99
print("%d" % num)
pass
# 在函數內部定義的變量,不能在其他位置使用
# print(num) 這裏如果這樣寫的話會報錯
demo1()
demo2()
# 運行結果
在demo1函數內部的變量是 10
99
全局變量:
# 全局變量
num = 10
def demo1():
print("demo1 ==> %d" % num)
def demo2():
print("demo2 ==> %d" % num)
demo1()
demo2()
# 運行結果
demo1 ==> 10
demo2 ==> 10
函數不能修改全局變量的值,因爲函數是處於局部之內,但是如果函數想修改全局變量的話可以將變量前聲明成global,這樣這個變量就變成了全局變量。global 關鍵字會告訴解釋器後面的變量是一個全局變量,再使用賦值語句時就不會創建局部變量。我們在開發程序時,應該將所有的全局變量放在代碼開始的地方,也就是先導入包和模塊,再就是定義全局變量,這樣在後面使用的時候就不會出問題。
函數多個返回值
Python函數可以有多個返回值,當有多個返回值時,其返回的數據類型是元組,可以使用多個變量來接收元組裏的數據,但要保持數量一致。
def measure():
"""測量溫度和溼度"""
print("測量開始...")
temp = 39
wetness = 50
print("測量結束...")
# 元組-可以包含多個數據,因此可以使用元組讓函數一次返回多個值
# 如果函數返回的類型是元組,小括號可以省略
# return (temp,wetness)
return temp,wetness
# 元組
result = measure()
print(result)
# 需要單獨的處理溫度或溼度-不方便
print(result[0])
print(result[1])
# 如果函數返回的類型是元組,同時希望單獨的處理元組中的元素
# 可以使用多個變量,一次接收函數的返回結果
# 注意:使用多個變量接收結果時,變量的個數應該和元組中元素的個數保持一致
gl_temp, gl_wetness = measure()
print(gl_temp)
print(gl_wetness)
# 運行結果
測量開始...
測量結束...
(39, 50)
39
50
測量開始...
測量結束...
39
50
交換變量
學C語言的時候肯定遇到過一個題目叫你交換兩個變量的值,冒泡排序的時候就會用到,什麼t = a[j];a[j] = a[j+1];a[j+1] = t;這樣的東西,轉來轉去是不是賊麻煩。Python中有一種特有的方法來交換兩個變量的值:a, b = (b, a) 就這麼一個語句就可以交換a,b兩個變量的值。
可變參數和不可變參數
在函數內部,針對參數使用賦值語句,不會修改到外部的實參變量;但是如果使用的是方法,也就是函數,可以修改實參變量。
def demo(num, num_list):
print("函數內部的代碼")
num = 100
num_list = [1, 2, 3]
print(num)
print(num_list)
print("函數執行完成")
gl_num = 99
gl_list = [4, 5, 6]
demo(gl_num, gl_list)
print(gl_num)
print(gl_list)
# 運行結果
函數內部的代碼
100
[1, 2, 3]
函數執行完成
99
[4, 5, 6]
def demo(num_list):
print("函數內部的代碼")
# 使用方法修改列表的內容
num_list.append(9)
print(num_list)
print("函數執行完成")
gl_list = [1, 2, 3]
demo(gl_list)
print(gl_list)
# 運行結果
函數內部的代碼
[1, 2, 3, 9]
函數執行完成
[1, 2, 3, 9]
函數的缺省參數
前面講列表那一塊的時候有介紹到sort()函數,默認是升序排序,如果添加一個參數sort(reverse=True)的話就是降序排序了,這裏sort函數中的reverse就是一個缺省參數,默認有缺省值。函數在定義時,如果某個參數設置了默認值,那麼在調用這個函數的時候,想默認使用的話就可一不用傳遞參數,如果傳遞參數的話,就會修改默認值。在指定缺省參數的默認值時,應該使用最常見的值作爲默認值。
def print_info(name,gender = True):
"""
:param name: 班上同學的姓名
:param gender: True 男生 False 女生
"""
gender_text = "男生"
if not gender:
gender_text = "女生"
print("%s是%s" % (name,gender_text))
# 假設班上的同學,男生居多
# 提示:在指定缺省參數的默認值時,應該使用最常見的值作爲默認值
print_info("小明")
print_info("老王")
print_info("小美", False)
多值參數
當一個Python函數想要接收不定個數的參數時就可以使用多值參數。多值參數有兩種:一種是參數前面加一個*;另一種是參數前面加兩個*。例如:*args:存放元組參數;**kwargs:存放字典參數。
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200306153243421.png
def demo(num, *nums, **person):
print(num)
print(nums)
print(person)
demo(1)
demo(1, 2, 3, 4, name="小明", age=18)
# 運行結果
1
()
{}
1
(2, 3, 4)
{'name': '小明', 'age': 18}
num是默認是一個數字變量,所以輸出一個1;*nums是元組,輸出爲(2, 3, 4);**person是字典,輸出爲{‘name’: ‘小明’, ‘age’: 18}。
多值參數求和:
def sum_numbers(*args):
num = 0
print(args)
# 循環遍歷
for n in args:
num += n
return num
result = sum_numbers(1, 2, 3)
print(result)
# 運行結果
(1, 2, 3)
6
元組和字典的拆包
在調用帶有多值參數的函數時,如果希望將一個元組變量傳遞給args,將一個字典變量傳遞給kwargs,就可以選擇拆包,簡化參數傳遞,也就是告訴函數,我這裏的哪一部分是元組,我要你全部輸出,那一部分是字典,再全部輸出,相當於打了一個包。
def demo(*args, **kwargs):
print(args)
print(kwargs)
# 元組變量/字典變量
gl_nums = (1, 2, 3)
gl_dict = {"name": "小明", "age": 18}
# demo(gl_nums, gl_dict)
# 拆包語法,簡化元組變量/字典變量的傳遞
demo(*gl_nums, **gl_dict)
demo(1, 2, 3,name="小明", age=18)
# 運行結果
(1, 2, 3)
{'name': '小明', 'age': 18}
(1, 2, 3)
{'name': '小明', 'age': 18}
遞歸函數
大家學過C語言的應該都瞭解一點遞歸,遞歸函數就是函數自己調用自己,在自己調用自己的時候,要給出遞歸的出口,不然函數就會一直執行下去,成了個死循環。有時候解決複雜問題時可以選擇遞歸,但是有的時候遞歸會佔用過多的內存和時間。
def sum_number(num):
print(num)
# 遞歸的出口,當參數滿足某個條件時,不再執行函數
if num == 1:
return
# 自己調用自己
sum_number(num-1)
sum_number(3)
# 運行結果
3
2
1
最後
訪問量破千,一起加油!
寫博客是爲了記錄和分享自己的學習歷程,溫故知新!做的不好的地方歡迎指正!!!