程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python函數定義的高級用法

編輯:Python

函數定義時的幾類常見參數:

1、默認參數

看如下代碼

def stu_register(name,age,country,course):
print("----注冊學⽣生信息------")
print("姓名:",name)
print("age:",age)
print("國籍:",country)
print("課程:",course)
stu_register("王⼭山炮",22,"CN","python_devops")
stu_register("張叫春",21,"CN","linux")
stu_register("劉⽼老老根",25,"CN","linux")

發現 country 這個參數 基本都 是”CN”, 就像我們在⽹網站上注冊⽤用戶,像國籍這種信息,你不不填寫,默認 就會是 中國, 這就是通過默認參數實現的,把country變成默認參數⾮非常簡單

def stu_register(name,age,course,country="CN"):

這樣,這個參數在調⽤用時不不指定,那默認就是CN,指定了了的話,就⽤用你指定的值。

另外,你可能注意到了了,在把country變成默認參數後,我同時把它的位置移到了了最後⾯面,為什麼 呢?
這是語法強制的,默認參數放在其他參數後邊,為啥呢? 假設允許這樣:

def stu_register(name,age,country="CN",course):

那調⽤用時

stu_register("Mack",22,"Python","US")

你告訴我,第3個參數 python 到底應該給到country還是course呢? ⽆無論給哪個,都會出現歧義,所以 Python語法⼲干脆就讓你把默認參數放最後, 解釋器在處理理函數時參數時,按優先級,位置參數>默認參數

二、關鍵參數(指定參數)

正常情況下,給函數傳參數要按順序,不不想按順序就可以⽤用關鍵參數,只需指定參數名即可(指定了了參數 名的參數就叫關鍵參數),但記住⼀一個要求就是, 關鍵參數必須放在位置參數(以位置順序確定對應關系的參數)之後。


def stu_register(name, age, course='PY' ,country='CN'):
print("----注冊學⽣生信息------")
print("姓名:", name)
print("age:", age)
print("國籍:", country)
print("課程:", course)

調⽤用可以這樣( 正確的調用方式:

stu_register("王⼭山炮",course='PY', age=22,country='JP' )

但絕不可以這樣

stu_register("王⼭山炮",course='PY',22,country='JP' )

當然這樣也不⾏

stu_register("王⼭山炮",22,age=25,country='JP' )

這樣相當於給age賦值2次,會報錯!
注意,參數優先級順序是 位置參數>關鍵參數

三、⾮固定參數

若你的函數在定義時不不確定⽤用戶想傳⼊入多少個參數,就可以使⽤用⾮固定參數

def stu_register(name,age,*args): # *args 會把多傳⼊入的參數變成⼀一個元組形式 
print(name,age,args)
stu_register("Alex",22)
#輸出
#Alex 22 () #後⾯面這個()就是args,只是因為沒傳值,所以為空
stu_register("Jack",32,"CN","Python") #輸出
# Jack 32 ('CN', 'Python')

還可以有⼀個 **kwargs

def stu_register(name,age,*args,**kwargs): # *kwargs 會把多傳⼊入的參數變成⼀一個dict形 式
print(name,age,args,kwargs)
stu_register("Alex",22)
#輸出
#Alex 22 () {}#後⾯面這個{}就是kwargs,只是因為沒傳值,所以為空
stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong") #輸出
# Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}

1.5 局部變量量與全局變量量

看如下代碼

name = "Alex Li" def change_name():
name = "金⻆大王, ⼀個有Tesla的高級屌絲" print("after change", name)
change_name() print("在外面看name改了了麼?",name)
# 輸出
>>>
after change ⾦⻆大王,⼀個有Tesla的高級屌絲 在外⾯看name改了了麼? Alex Li

為什麼在函數內部改了name的值後, 在外面print的時候卻沒有改呢? 因為這兩個name根本不是⼀回事

  • 在函數中定義的變量稱為局部變量,在程序的⼀開始定義的變量稱為全局變量。
  • 全局變量作用域(即有效范圍)是整個程序,局部變量作⽤域是定義該變量的函數。
  • 變量的查找順序是局部變量>全局變量
  • 當全局變量與局部變量同名時,在定義局部變量的函數內,局部變量起作⽤;在其它地⽅方全局變量量起作⽤。
  • 在函數⾥是不能直接修改全局變量的。

就是想在函數⾥裡裡修改全局變量量怎麼辦?

name = "Alex Li"
def change_name():
global name #聲明⼀一個全局變量量
name = "Alex ⼜又名⾦金金⻆角⼤大王,愛⽣生活、愛⾃自由、愛姑娘"
print("after change",name)
change_name()
print("在外⾯面看看name改了了麼?", name)

global name 的作⽤就是要在函數⾥聲明全局變量name ,意味著最上⾯的 name = “Alex Li” 即使不寫,程序最後面的print也可以打印name。雖然可以改,但不不建議⽤這個global語法,隨著代碼增多 ,會造成代碼調試困難。

1.6 內置函數

每個函數的作⽤用我都幫你標好了了

1. abs # 求絕對值
2. all #Return True if bool(x) is True for all values x in the iterable.If the iterable is empty, return
True.
3. any #Return True if bool(x) is True for any x in the iterable.If the iterable is empty, return
False.
4. ascii #Return an ASCII-only representation of an object,ascii(“中國”) 返回”‘\u4e2d\u56fd’”
5. bin #返回整數的2進制格式
6. bool # 判斷⼀一個數據結構是True or False, bool({}) 返回就是False, 因為是空dict
7. bytearray # 把byte變成 bytearray, 可修改的數組
8. bytes # bytes(“中國”,”gbk”)
9. callable # 判斷⼀一個對象是否可調⽤用
10. chr # 返回⼀一個數字對應的ascii字符 , ⽐比如chr(90)返回ascii⾥裡裡的’Z’
11. classmethod #⾯面向對象時⽤用,現在忽略略
12. compile #py解釋器器⾃自⼰己⽤用的東⻄西,忽略略
13. complex #求復數,⼀一般⼈人⽤用不不到
14. copyright #沒⽤用
15. credits #沒⽤用
16. delattr #⾯面向對象時⽤用,現在忽略略
17. dict #⽣生成⼀一個空dict
18. dir #返回對象的可調⽤用屬性
19. divmod #返回除法的商和余數 ,⽐比如divmod(4,2),結果(2, 0)
20. enumerate #返回列列表的索引和元素,⽐比如 d = [“alex”,”jack”],enumerate(d)後,得到(0, ‘alex’)
(1, ‘jack’)
21. eval #可以把字符串串形式的list,dict,set,tuple,再轉換成其原有的數據類型。
22. exec #把字符串串格式的代碼,進⾏行行解義並執⾏行行,⽐比如exec(“print(‘hellworld’)”),會解義⾥裡裡⾯面的字符
串串並執⾏行行
23. exit #退出程序
24. filter #對list、dict、set、tuple等可迭代對象進⾏行行過濾, filter(lambda x:x>10,
[0,1,23,3,4,4,5,6,67,7])過濾出所有⼤大於10的值
25. float #轉成浮點
26. format #沒⽤用
27. frozenset #把⼀一個集合變成不不可修改的
28. getattr #⾯面向對象時⽤用,現在忽略略
29. globals #打印全局作⽤用域⾥裡裡的值
30. hasattr #⾯面向對象時⽤用,現在忽略略
31. hash #hash函數
32. help
33. hex #返回⼀一個10進制的16進制表示形式,hex(10) 返回’0xa’
34. id #查看對象內存地址
35. input
36. int
37. isinstance #判斷⼀一個數據結構的類型,⽐比如判斷a是不不是fronzenset, isinstance(a,frozenset) 返
回 True or False
38. issubclass #⾯面向對象時⽤用,現在忽略略
39. iter #把⼀一個數據結構變成迭代器器,講了了迭代器器就明⽩白了了
40. len
41. list
42. locals
43. map # map(lambda x:x**2,[1,2,3,43,45,5,6,]) 輸出 [1, 4, 9, 1849, 2025, 25, 36]
44. max # 求最⼤大值
45. memoryview # ⼀一般⼈人不不⽤用,忽略略
46. min # 求最⼩小值
47. next # ⽣生成器器會⽤用到,現在忽略略
48. object #⾯面向對象時⽤用,現在忽略略
49. oct # 返回10進制數的8進制表示
50. open
51. ord # 返回ascii的字符對應的10進制數 ord(‘a’) 返回97,
52. print
53. property #⾯面向對象時⽤用,現在忽略略
54. quit
55. range
56. repr #沒什什麼⽤用
57. reversed # 可以把⼀一個列列表反轉
58. round #可以把⼩小數4捨5⼊入成整數 ,round(10.15,1) 得10.2
59. set
60. setattr #⾯面向對象時⽤用,現在忽略略
61. slice # 沒⽤用
62. sorted
63. staticmethod #⾯面向對象時⽤用,現在忽略略
64. str
65. sum #求和,a=[1, 4, 9, 1849, 2025, 25, 36],sum(a) 得3949
66. super #⾯面向對象時⽤用,現在忽略略
67. tuple
68. type
69. vars #返回⼀一個對象的屬性,⾯面向對象時就明⽩白了了
70. zip #可以把2個或多個列列表拼成⼀一個, a=[1, 4, 9, 1849, 2025, 25, 36],b = [“a”,”b”,”c”,”d”],
list(zip(a,b)) #得結果 [(1, 'a'), (4, 'b'), (9, 'c'), (1849, 'd')]

1.7 模塊導⼊入&調⽤用

導入模塊有以下幾種⽅方式:

import module_a #導⼊
from module import xx # 導入某個模塊下的某個⽅法 or ⼦模塊
from module.xx.xx import xx as rename #導⼊後⼀個⽅法後重命令 
from module.xx.xx import * #導⼊⼀個模塊下的所有⽅法,不建議使⽤
module_a.xxx #調⽤

注意:模塊⼀旦被調⽤,即相當於執⾏了另外⼀個py⽂文件⾥的代碼

1.8 ⾃定義模塊

這個最簡單, 創建⼀個.py⽂文件,就可以稱之為模塊,就可以在另外一個程序⾥導⼊。

1.9 模塊的查找路徑

有沒有發現,⾃⼰寫的模塊只能在當前路徑下的程序裡才能導⼊,換一個目錄再導⼊自己的模塊就報錯。說找不到了, 這是為什麼? 這與導⼊模塊的查找路徑有關。

import sys
print(sys.path)

輸出(注意不不同的電腦可能輸出的不不太⼀一樣)


['', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site- packages']

你導入⼀個模塊時,Python解釋器會按照上⾯列表順序去依次到每個⽬錄下去匹配你要導⼊的模塊名, 只要在⼀個⽬目錄下匹配到了了該模塊名,就⽴刻導⼊入,不再繼續往後找。
注意列表第⼀個元素為空,即代表當前⽬錄,所以你⾃己定義的模塊在當前目錄會被優先導⼊入。
我們自⼰創建的模塊若想在任何地⽅都能調用,那就得確保你的模塊⽂件⾄少在模塊路徑的查找列表中。
我們⼀般把自⼰寫的模塊放在⼀個帶有“site-packages”字樣的⽬錄⾥,我們從⽹上下載安裝的各種第三方的模塊⼀般都放在這個⽬錄。

1.10 第3⽅方開源模塊安裝

那如何從這個平台上下載代碼呢?

  1. 直接在上⾯面這個⻚頁⾯面上點download,下載後,解壓並進⼊入⽬目錄,執⾏行行以下命令完成安裝
編譯源碼
python setup.py build 安裝源碼
python setup.py install
  1. 直接通過pip安裝
pip3 install paramiko #paramiko 是模塊名
# pip命令會⾃自動下載模塊包並完成安裝。

軟件⼀一般會被⾃自動安裝你python安裝⽬目錄的這個⼦子⽬目錄⾥裡裡

/your_python_install_path/3.6/lib/python3.6/site-packages

pip命令默認會連接在國外的python官⽅方服務器器下載,速度⽐比較慢,你還可以使⽤用國內的⾖豆瓣源,數據 會定期同步國外官⽹網,速度快好多。

 pip install -i http://pypi.douban.com/simple/ alex_sayhi --trusted-host pypi.douban.com #alex_sayhi是模塊名
  • -i 後⾯跟的是⾖瓣源地址
  • —trusted-host 得加上,是通過網站https安全驗證⽤的

1.11 什麼是包(package)

若你寫的項⽬較復雜,有很多代碼⽂件的話,為了方便便管理,可以⽤包來管理。 ⼀個包其實就是⼀個⽂件⽬錄,你可以把屬於同一個業務線的代碼⽂件都放在同一個包⾥。

如何創建⼀一個包?

只需要在目錄下創建⼀個空的 __init__.py ⽂件 , 這個目錄就變成了包。這個⽂件叫包的初始化⽂件 ,一般為空,當然也可以寫東西,當你調⽤這個包下及其任意⼦包的的任意模塊時, 這個 __init__.py ⽂件都會先執⾏。

以下 有a、b 2個包,a2是a的⼦包,b2是b的⼦包。

若在a_module.py模塊⾥導⼊b2_mod.py的話,怎麼辦?

a_module.py的⽂件路徑為
/Users/alex/Documents/work/PyProjects/py8days_camp/day6/課件/a/a2/a_module.py

想導入成功,直接寫以下代碼就可以( 正確調用方式

from day6.課件.b.b2 import b2_mod

為何從day6開始?⽽不是從 py8days_camp 或 課件 開始呢?
因為你的sys.path列列表裡,已經添加了相關的路徑

['/Users/alex/Documents/work/PyProjects/py8days_camp/day6/課件/a/a2', '/Users/alex/Documents/work/PyProjects/py8days_camp', # <---就是這個。。 
'/Applications/PyCharm.app/Contents/helpers/pycharm_display',
'/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip',
'/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6',
'/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload',
'/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site- packages',
'/Applications/PyCharm.app/Contents/helpers/pycharm_matplotlib_backend']

手動添加sys.path路徑

你會說,我沒有添加這個 ‘/Users/alex/Documents/work/PyProjects/py8days_camp’ 呀,它是怎
麼進到 sys.path 裡的?

答案是Pycharm自動幫你添加的,若你脫離pycharm再執⾏這個 a_module.py 就會報錯了。


Alexs-MacBook-Pro:a2 alex$ python3 a_module.py Traceback (most recent call last):
File "a_module.py", line 7, in <module> from day6.課件.b.b2 import b2_mod
ModuleNotFoundError: No module named 'day6'

不⽤用慌, ⾃己手動添加sys.path路徑就可以。

手動添加sys.path路徑的實現方式:

import os
import sys
base_dir=os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.pa th.dirname(os.path.abspath(__file__)))))) # 取到路路 徑/Users/alex/Documents/work/PyProjects/py8days_camp
print(base_dir)
sys.path.append(base_dir) # 添加到sys.path⾥裡裡
from day6.課件.b.b2 import b2_mod

二、⼏個常⽤Python模塊

2.1 系統調⽤用OS模塊

os 模塊提供了很多允許你的程序與操作系統直接交互的功能。

import os
得到當前工作⽬錄,即當前Python腳本工作的⽬錄路徑: os.getcwd()
返回指定⽬錄下的所有⽂件和⽬錄名:os.listdir()
函數用來刪除⼀個文件:os.remove()
刪除多個目錄:os.removedirs(r“c:\python”)
檢驗給出的路徑是否是⼀個⽂件:os.path.isfile()
檢驗給出的路徑是否是一個⽬錄:os.path.isdir()
判斷是否是絕對路路徑:os.path.isabs()
檢驗給出的路徑是否真地存:os.path.exists()
返回⼀個路徑的⽬錄名和文件名:os.path.split() e.g
os.path.split('/home/swaroop/byte/code/poem.txt') 結果: ('/home/swaroop/byte/code', 'poem.txt')
分離擴展名:os.path.splitext() 結果:('/usr/local/test', '.py')
e.g os.path.splitext('/usr/local/test.py')
獲取路徑名:os.path.dirname()
獲得絕對路徑: os.path.abspath()
獲取⽂件名:os.path.basename()
運⾏shell命令: os.system()
讀取操作系統環境變量HOME的值:os.getenv("HOME")
返回操作系統所有的環境變量: os.environ
設置系統環境變量,僅程序運⾏行行時有效:os.environ.setdefault('HOME','/home/alex')
給出當前平台使⽤的⾏終止符:os.linesep Windows使用'\r\n',Linux and MAC使用'\n'
指示你正在使用的平台:os.name 對於Windows,它是'nt',⽽對於Linux/Unix⽤用戶,它是'posix'
重命名:os.rename(old, new)
創建多級⽬錄:os.makedirs(r“c:\python\test”)
創建單個⽬錄:os.mkdir(“test”)
獲取文件屬性:os.stat(file) 修改文件權限與時間戳:os.chmod(file)
獲取文件⼤小:os.path.getsize(filename)
結合⽬目錄名與⽂文件名:os.path.join(dir,filename)
改變⼯工作⽬目錄到dirname: os.chdir(dirname)
獲取當前終端的⼤大⼩小: os.get_terminal_size()
殺死進程: os.kill(10884,signal.SIGKILL)

2.2 time 模塊 在平常的代碼中,我們常常需要與時間打交道。在Python中,與時間處理理有關的模塊就包括:time,datetime, calendar(很少用,不講),下⾯分別來介紹。

我們寫程序時對間的處理可以歸為以下3種:

  • 時間的顯示,在屏幕顯示、記錄⽇志等 “2022-03-04” ;
  • 時間的轉換,⽐如把字符串格式的⽇期轉成Python中的⽇日期類型;
  • 時間的運算,計算兩個日期間的差值等。

在Python中,通常有這⼏種⽅式來表示

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved