函數(shù)
函數(shù)是一大塊可重用的代碼糙置。它是有名稱的代碼塊免糕,接受輸入、提供輸出并可存儲(chǔ)在文件中供以后使用跟衅。
給函數(shù)名賦值
>>> dir = 3
>>> dir
3
>>> dir()
Traceback (most recent call last):
File "<pyshell#28>", line 1, in <module> dir()
TypeError: 'int' object is not callable
這里讓dir 指向了數(shù)字3孵睬, 導(dǎo)致你再也無法訪問dir原來指向的函數(shù)!要恢復(fù)原樣伶跷,需要重啟Python掰读。
定義函數(shù)
與變量名一樣,函數(shù)名也只能包含字母叭莫、數(shù)字和下劃線_蹈集,而且不能以數(shù)字打頭。
下面是一個(gè)計(jì)算圓面積的函數(shù):
# area.py
import math
def area(radius):
"""
Return the area of a circle
with the given radius.
For example:
>>> area(5.5)
95.03317777109125
"""
return math.pi * radius ** 2
一種格式約定
Python文檔字符串通常遵循一種標(biāo)準(zhǔn)的格式約定:用三引號(hào)標(biāo)識(shí)文檔字符串的開始和結(jié)束位置食寡;第1行是函數(shù)的簡(jiǎn)要描述雾狈;接下來是詳情和示例廓潜。
文檔字符串的其他好處
與內(nèi)置函數(shù)一樣抵皱,你也可輕松地查看自己編寫的函數(shù)的文檔字符串,如下所示:
>>> print(area.__doc__)
Returns the area of a circle with the given radius.
For example:
>>> area(5.5)
95.03317777109125
當(dāng)在IDLE編輯器中調(diào)用area時(shí)辩蛋,IDLE將自動(dòng)讀取該函數(shù)的文檔字符串呻畸,并將其作為工具提示顯示出來。
Python還有一個(gè)很有用的工具——doctest悼院,可用于自動(dòng)運(yùn)行文檔字符串中的Python示例代碼伤为。
函數(shù)的組成部分
屬于說明
除了返回值外,函數(shù)以其他任何方式所做的修改都被稱為副作用(side effect)据途;打印到屏幕绞愚、寫入文件和下載網(wǎng)頁都屬于副作用。
有一種名為函數(shù)式編程的編程風(fēng)格颖医,其特征是幾乎消除了副作用位衩。在函數(shù)式編程中,你只能通過返回值來完成修改熔萧。
使用正確的情況下糖驴,函數(shù)式編程是非常優(yōu)雅而又強(qiáng)大的程序編寫方式僚祷。
變量的作用域
全局變量
要訪問全局變量,必須使用關(guān)鍵字global:
name = 'Jack'
def say_hello():
print('Hello' + name + '!')
def change_name(new_name):
global name
name = new_name
>>> say_hello()
Hello Jack!
>>> say_hello()
Hello Piper!
使用main函數(shù)
其他語言中的main函數(shù)
使用main函數(shù)的做法非常普遍贮缕,有些編程語言(最著名的是C辙谜、C++和Java),還要求必須使用main函數(shù)感昼。但在Python中装哆,main只是一種約定,完全是可選的定嗓。
使用main函數(shù)的優(yōu)點(diǎn)是烂琴,可更輕松地反復(fù)運(yùn)行程序,還可傳遞輸入值蜕乡。
函數(shù)的參數(shù)
按引用傳遞
向函數(shù)傳遞參數(shù)時(shí)奸绷,Python采用按引用傳遞的方式。這意味著當(dāng)你傳遞參數(shù)時(shí)层玲,函數(shù)將使用新變量名來引用原始值号醉。例如:
def add(a, b):
return a + b
>>> x, y = 3, 4
>>> add(x, y)
7
在第一行設(shè)置x和y后,x辛块、y將分別指向3和4.當(dāng)調(diào)用add(x, y)時(shí)畔派,Python創(chuàng)建兩個(gè)新變量——a 和 b砸讳,它們分別指向x和y的值解藻。并沒有復(fù)制實(shí)參的值,而是給它們指定新名稱纽窟,而函數(shù)將使這些新名稱來引用它們尘盼。
將a和b相加后憨愉,函數(shù)返回,而a和b被自動(dòng)刪除卿捎。在整個(gè)函數(shù)調(diào)用過程中配紫,x和y為未受影響。
按值傳遞
有些編程語言(如C++)可按值傳遞參數(shù)午阵。按置傳遞參數(shù)時(shí)躺孝,將創(chuàng)建其拷貝,并將該拷貝傳遞給函數(shù)底桂。如果傳遞的值很大植袍,復(fù)制可能消耗大量時(shí)間和內(nèi)存。Python不支持按值傳遞籽懦。
一個(gè)重要示例
按引用傳遞簡(jiǎn)單而高效于个,但是有些事它做不了。例如:
def set1(x):
x = 1
函數(shù)set1想將傳入的變量的值設(shè)置為1
>>> m = 5
>>> set1(m)
>>> m
5
m的值根本沒變猫十。為幫助理解览濒,將這個(gè)示例分解成下面幾步:
- 將5賦給m呆盖。
- 調(diào)用set1(m): 將m的值賦給x,這樣m和x都指向5贷笛。
- 將1賦給x应又。
- 函數(shù)set1結(jié)束后,x被刪除乏苦。
在函數(shù)set1中株扛,根本不能訪問變量m。
默認(rèn)值
同Kotlin
關(guān)鍵字參數(shù)
在Python中汇荐,另一種很有用的參數(shù)指定方式是使用關(guān)鍵字洞就。例如:
def shop(where = 'store',
what = 'pasta',
howmuch = '10 pounds'):
print('I want you to go to the', where)
print('and buy', howmuch, 'of', what + '.')
使用關(guān)鍵字參數(shù)的函數(shù)式:
>>> shop()
I want you to go to the store and buy 10 pounds of pasta.
>>> shop(howmuch = 'a ton', what = 'towels', where = 'bakery')
I want you to go to the bakery and buy a ton of towels.
關(guān)鍵字參數(shù)有兩大好處:
- 清晰地指出了參數(shù)值,提高了程序的可讀性掀淘;
- 關(guān)鍵字參數(shù)的順序無關(guān)緊要旬蟋。
模塊
模塊是一系列相關(guān)的函數(shù)和變量。
創(chuàng)建Pyton模塊
要?jiǎng)?chuàng)建模塊革娄,可創(chuàng)建一個(gè).py文件倾贰,在其中包含用于完成任務(wù)的函數(shù)。
例如拦惋,下面是一個(gè)在屏幕上打印形狀的模塊:
# shapes.py
"""
A collection of functions for printing basic shapes.
"""
CHAR = '*'
def rectangle(height, width):
""" Prints a rectangle """
for row in range(height):
for col in range(width):
print(CHAR, end='')
print()
def square(side):
""" Prints a square """
rectangle(side, side)
def triangle(height):
""" Prints a right triangle. """
for row in range(height):
for col in range(1, row + 2):
print(CHAR, end=' ')
print()
模塊與常規(guī)Python程序之間唯一的差別是用途不同:模塊是一個(gè)由函數(shù)組成的工具箱匆浙,用于編寫其他程序。因此厕妖,模塊通常沒有main()函數(shù)首尼。
要使用模塊,只需導(dǎo)入它即可言秸。例如:
>>> import shapes
>>> dir(shapes)
['CHAR', '__builtins__',...,'triangle']
>>> print(shapes.__doc__)
A collection of functions for printing basic shapes.
>>> shapes.CHAR
'*'
還可以導(dǎo)入模塊的所有內(nèi)容:
>>> from shapes import *
>>> rectangle(3, 8)
********
********
********
名稱空間
對(duì)于模塊软能,很有用的一點(diǎn)是它們形成名稱空間
。名稱空間基本上就是一組獨(dú)特的變量名和函數(shù)名井仰。要讓模塊中的名稱在模塊外面可見埋嵌,你必須使用import
語句。
import *
容易導(dǎo)致名稱沖突俱恶,盡量減少這樣的使用。