網站首頁 編程語言 正文
一、定義函數
在Python中可以使用def關鍵字來定義函數,命名規則跟變量的命名規則是一致的。在函數名后面的圓括號中可以放置傳遞給函數的參數,而函數執行完成后我們可以通過return關鍵字來返回一個值。
定義代碼如下:
def fac(num): ? ? """求階乘""" ? ? result = 1 ? ? for n in range(1, num + 1): ? ? ? ? result *= n ? ? #返回值 ? ? return result
二、函數的參數
在Python中,函數的參數可以有默認值,也支持使用可變參數,所以Python并不需要像其他語言一樣支持函數的重載,因為我們在定義一個函數的時候可以讓它有多種不同的使用方式,
下面是兩個小例子:
from random import randint ? ? def roll_dice(n=2): ? ? """搖色子""" ? ? total = 0 ? ? for _ in range(n): ? ? ? ? total += randint(1, 6) ? ? return total ? ? def add(a=0, b=0, c=0): ? ? """三個數相加""" ? ? return a + 2 * b + 3 * c ? ? # 如果沒有指定參數那么使用默認值搖兩顆色子 print(roll_dice()) # 搖三顆色子 print(roll_dice(3)) #函數重載,沒有指定函數變量時,參數按照順序傳值 print(add()) print(add(1)) print(add(1, 2)) print(add(1, 2, 3)) # 傳遞參數時可以不按照設定的順序進行傳遞 print(add(c=50, a=100, b=200)) # 或者可以不傳 print(add(c=50, b=200)) ? if __name__ == '__main__': ? ? pass
沒有傳入對應參數的值時將使用該參數的默認值。
不確定參數個數的時候,我們可以使用可變參數,代碼如下所示:
# 在參數名前面的*表示args是一個可變參數 def add(*args): ? ? total = 0 ? ? for val in args: ? ? ? ? total += val ? ? return total ? ? # 在調用add函數時可以傳入0個或多個參數 print(add()) print(add(1)) print(add(1, 2)) print(add(1, 2, 3)) print(add(1, 3, 5, 7, 9))
三、用模塊管理函數
由于Python沒有函數重載的概念,那么后面的定義函數會覆蓋之前的定義,也就意味著兩個函數同名函數實際上只有一個是存在的。
def foo(): ? ? print('hello, world!') ? ? def foo(): ? ? print('goodbye, world!') ? ? # 下面的代碼會輸出什么呢? foo() ? if __name__ == '__main__': ? ? pass ? #實際輸出 goodbye, world!
多人協作進行團隊開發的時候,團隊中可能有多個程序員都定義了名為foo的函數,那么怎么解決這種命名沖突呢?
重點如何避免函數覆蓋!!!
在Python中每個.py文件就代表了一個模塊(module),我們在不同的模塊中可以有同名的函數,在使用函數的時候我們通過import
關鍵字導入指定的模塊就可以區分到底要使用的是哪個模塊中的foo
函數,
代碼如下所示:
module1.py ? def foo(): ? ? print('hello, world!') ? module2.py ? def foo(): ? ? print('goodbye, world!')
導入模塊:
test.py ? import module1 as m1 import module2 as m2 ? m1.foo() m2.foo()
注意:但是如果將代碼寫成了下面的樣子,那么程序中調用的是最后導入的那個foo,因為后導入的foo覆蓋了之前導入的foo。
from module1 import foo from module2 import foo ? # 輸出goodbye, world!,使用的是后導入的模塊 foo()
需要說明的是,如果我們導入的模塊除了定義函數之外還有可以執行代碼,那么Python解釋器在導入這個模塊時就會執行這些代碼,事實上我們不想執行這些代碼,那我們將可執行代碼放入如下所示的條件中,這樣的話除非直接運行該模塊,if條件下的這些代碼是不會執行的,因為只有直接執行的模塊的名字才是"__main__"
。
def foo(): ? ? pass ? def bar(): ? ? pass ? # __name__是Python中一個隱含的變量它代表了模塊的名字 # 只有被Python解釋器直接執行的模塊的名字才是__main__ if __name__ == '__main__': ? ? print('call foo()') ? ? foo() ? ? print('call bar()') ? ? bar()
import module3 # 導入module3時 不會執行模塊中if條件成立時的代碼 因為模塊的名字是module3而不是__main__
四、變量的作用域?
def foo(): ? ? b = 'hello' ? ? ? # Python中可以在函數內部再定義函數 ? ? def bar(): ? ? ? ? c = True ? ? ? ? print(a) ? ? ? ? print(b) ? ? ? ? print(c) ? ? ? bar() ? ? # print(c) ?# NameError: name 'c' is not defined ? ? if __name__ == '__main__': ? ? a = 100 ? ? # print(b) ?# NameError: name 'b' is not defined ? ? foo()
打印結果:
100
hello
True
上面的代碼能夠順利的執行并且打印出100、hello和True,但我們注意到了,在bar函數的內部并沒有定義a和b兩個變量,那么a和b是從哪里來的。
我們在上面代碼的if分支中定義了一個變量a,這是一個全局變量(global variable),屬于全局作用域,因為它沒有定義在任何一個函數中。
在上面的foo函數中我們定義了變量b,這是一個定義在函數中的局部變量(local variable),屬于局部作用域,在foo函數的外部并不能訪問到它;但對于foo函數內部的bar函數來說,變量b屬于嵌套作用域,在bar函數中我們是可以訪問到它的。
bar函數中的變量c屬于局部作用域,在bar函數之外是無法訪問的。
Python查找變量順序:
“局部作用域”-》“嵌套作用域”-》“全局作用域”和“內置作用域”的順序進行搜索。
內置作用域:Python內置的那些標識符,我們之前用過的input、print、int等都屬于內置作用域。
我們希望通過函數調用修改全局變量a的值,但實際上下面的代碼是做不到的。
代碼如下:
def foo(): ? ? a = 200 ? ? print(a) ?# 200 ? ? if __name__ == '__main__': ? ? #這里變量值不能修改函數局部變量的值 ? ? a = 100 ? ? foo() ? ? print(a) ?# 100
在調用foo函數后,我們發現a的值仍然是100,這是因為當我們在函數foo中寫a = 200的時候,是重新定義了一個名字為a的局部變量,它跟全局作用域的a并不是同一個變量。
因為局部作用域中有了自己的變量a,因此foo函數不再搜索全局作用域中的a。如果我們希望在foo函數中修改全局作用域中的a,
代碼如下所示:
def foo(): ? ? global a ? ? a = 200 ? ? print(a) ?# 200 ? ? if __name__ == '__main__': ? ? a = 100 ? ? foo() ? ? print(a) ?# 200
可以使用global關鍵字來指示foo函數中的變量a來自于全局作用域。
注:
在實際開發中,我們應該盡量減少對全局變量的使用,因為全局變量的作用域和影響過于廣泛,可能會發生意料之外的修改和使用。
除此之外全局變量比局部變量擁有更長的生命周期,可能導致對象占用的內存長時間無法被垃圾回收
原文鏈接:https://blog.csdn.net/xp_lx1/article/details/124386797
相關推薦
- 2022-09-20 以SortedList為例詳解Python的defaultdict對象使用自定義類型的方法_pyth
- 2023-12-09 使用String.valueOf()的坑
- 2022-06-16 zap接收gin框架默認的日志并配置日志歸檔示例_Golang
- 2022-10-11 slearn缺失值處理器之Imputer詳析_python
- 2023-03-17 Go語言依賴管理三要素示例解析_Golang
- 2022-07-27 Python中的sys模塊、random模塊和math模塊_python
- 2021-12-02 深入了解c語言的循環語句_C 語言
- 2022-10-03 react事件對象無法獲取offsetLeft,offsetTop,X,Y等元素問題及解決_Reac
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支