理解函數
高中數學中,學習的函數 有一次函數,二次函數,高次函數,正餘弦函數,正餘切函數、指數函數、冪函數等等,都是函數。從這一節開始,學習程序中的函數。
f(x) = ax + b
其中a、 b是常數,x是變量,f(x)隨x的變化而變化。那麼x就叫做函數的自變量,而f(x)叫做函數的因變量。
假如x = 2,那麼上面的函數式可以寫爲f(x) = a * 2 + b
這樣就不難理解程序中的函數了。
由於函數本身是一個表達式,這個表達式會根據自變量x的變化而得到不同的結果。所以,程序中,編寫的函數也是爲了根據參數方便被重複調用。
可以把x當作程序中的參數來理解。
和數學中函數不同的是,程序中的函數的參數並不是一個數,它可以是任何對象。
對於變量的理解
在程序中,變量不僅僅指的是一個具體的數字,也可以是任何對象。
再來拿一個列子,比如f(x) = 2 * x + 3,
那麼在這個一次函數中,如果x=2 那麼,f(x)= 2 * 2 + 3
結果爲7,我們便稱這是一個映射。
所以X可以是任何對象,只是我們在數學中習慣了將它作爲一個數字。
可以這樣理解,X就是一個佔位符,因爲我們不知道函數具體想要實現什麼,那麼這個位置暫且先用x來代替,讓其佔着這個位置,等待交互模式下的輸入。
所以,程序中的變量說過來要比我們中學時期學過的函數要複雜的多。
關於變量的命名,Python中一般使用小寫字母來作爲變量的開頭,也可以是下劃線,以表示區別。
建立一個簡單的函數
>>> x = 3
>>> y = 2 * x + 3
>>> y
9
>>>
上面這個函數和中學學習的數學沒有任何區別,當然,在這就也沒有什麼實際的意義了,只是引出來作爲理解函數中的變量。
思考,如果我們這次讓x = 4 那麼y的值將會是多少?
>>> x = 3
>>> y = 2 * x + 3
>>> y
9
>>> x = 4
>>> y
9
>>>
發現,y的結果依然沒有變,爲什麼呢?
原因是這樣的,我們在前面提到過變量,在Python中,變量無類型,對象有類型,我們只是將3 這個對象貼上了變量x的標籤。經過第一次計算,y引用的依然是x = 3這個變量計算後的標籤8,所以,我們只有再進行一個計算,這個結果就會跟着變化了。
>>> x = 3
>>> y = 2 * x + 3
>>> y
9
>>> x = 4
>>> y
9
>>> y = 2 * x + 3
>>> y
11
>>>
有沒有發現,上面的函數在引用變量的時候,都是對變量進行先定義,然後再使用的,如果不預先定義,直接使用函數進行引用會發生什麼錯誤呢?
來看看:
>>> y = 2 * a + 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>>
上面的變量a是沒有預先定義的,所以,當直接用函數引用變量的時候出錯了。而且錯誤很明確,a 沒有被定義。
所以,無論是python還是java還是類C,對變量都是堅持先聲明,後使用的規則。記住這是規則。
在java中是這樣。
public class test{
public static void main(String args[]){
int c = a + 2;
System.out.println(c);
}
}
#然後再cmd命令窗口執行
D:\ProjectFiles\JavaFiles>javac test.java
test.java:3: 錯誤: 找不到符號
int c = a + 2;
^
符號: 變量 a
位置: 類 test
1 個錯誤
提示說找不到符號a ,那麼我們看代碼發現,並沒有定義變量a,然後我們定義一個變量a再進行運行程序
public class test{
public static void main(String args[]){
int a = 3;
int c = a + 2;
System.out.println(c);
}
}
#然後再cmd命令窗口執行:
D:\ProjectFiles\JavaFiles>javac test.java #編譯通過
D:\ProjectFiles\JavaFiles>java test
5
D:\ProjectFiles\JavaFiles>
java中的具體編譯結果,我在這裏就不解釋了。
C語言中是這樣的。
如果變量a未被定義:
#include <stdio.h>
void main(int){
int c = a + 3;
printf("%d", c);
}
錯誤 1 error C2065: “a”: 未聲明的標識符 d:\projectfiles\cfiles\consoleapplication1\consoleapplication1\源.cpp 3 1 ConsoleApplication1
2 IntelliSense: 未定義標識符 "a" d:\ProjectFiles\CFiles\ConsoleApplication1\ConsoleApplication1\源.cpp 3 10 ConsoleApplication1
如果a 被定義:
#include <stdio.h>
void main(int){
int a = 3;
int c = a + 3;
printf("%d", c);
}
將會在cmd窗口顯示一個結果6,
所以,再三聲明,無論是哪種編程語言,變量必須是先聲明,後使用。
建立實用的函數
上面寫的簡單函數只是爲了引進來讓理解函數和變量的關係。並沒有什麼實際的意義。所以,這次爲了讓函數“規範化”,寫一個.py的文件。
需求,定義一個函數,要求這個函數有兩個參數a,b,然後通過給函數傳遞參數,執行後並將結果輸出到屏幕上。
[root@python Script]# cat ftest.py
#!/usr/bin/env python
#coding:utf-8
def add(a,b):
c = a + b
print c
if __name__ == "__main__":
add(3,8)
[root@python Script]# python ftest.py
11
[root@python Script]#
說明:
def add(a,b):這是聲明一個名爲add並且參數爲a,b的函數。def也就是define定義的意思。
c = a + b :函數裏面的表達式塊,將a + b的結果賦值給c。
print c,將變量c 的結果輸出到屏幕上。
if name == “main“:這個暫時不用理解它,就當作程序的入口就行,記下來就行。
add(3,8):這個是調用前面定義的函數add並且傳入兩個實參3、8。
很好理解吧。
注意Python中函數的命名規則
· 函數名以數字、字母和下劃線組成
· def是Python中聲明函數的關鍵詞,也是define的簡寫。
· 函數名後面以一對圓括號結束,括號裏面可以有參數列表,也可以無參數列表,有參數列表的時候,參數列表數量並沒有限制
· 函數體當中的語句塊也是以四個空格爲縮進量。
練習:
減法函數:
>>> def sub(a,b):
... c = a - b
... print c
...
>>> sub(4,1)
3
>>>
乘法函數:
>>> def multiplication(a,b):
... c = a * b
... print c
...
>>> multiplication(4,5)
20
>>>
除法函數:
>>> def division(a,b):
... c = b / a
... print c
...
>>> division(3,9)
3
>>>
取餘函數:
>>> def remainer(a,b):
... c = a % b
... return c
...
>>> remainer(10,3)
1
>>>
說明:以上引入的參數都是沒有類型的,也一直提到變量無類型,只有對象纔是有類型的。所以在定義函數的時候,函數裏面的參數是不確定的,因爲它可以引用任何對象類型。只要函數體裏面的運算成立,變可以引用任何參數。如果函數體裏面的運算不成立,則會報錯。
示例
>>> def test(a,b):
... return a + b
...
>>> test("Python ","Java")
'Python Java'
>>> test("Python ",12345)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in test
TypeError: cannot concatenate 'str' and 'int' objects
第一次調用的時候,因爲兩個參數都是字符串,所以連接沒有問題,但是第二個調用函數的時候,一個是字符串,一個是整型數值,所以返回的運算語句是不成立的,所以報錯。不過可以在實參的傳遞中進行類型轉換。
>>> test("Python ",str(12345))
'Python 12345'
>>>
從實驗的結果中發現,返回的a + b完全取決於傳入參數的對象類型,而這種依賴關係被稱作多態,因爲Python也是一種面向對象的編程語言,所以,在這裏引出面向對象的三大特性,繼承、封裝、多態。
注意,Python中,爲對象編寫接口,而不是爲數據類型編寫接口
命名
Python中,命名的一般要求:
文件: 全小寫,也可以使用下劃線
函數名: 小寫,和下劃線使用,提高程序的可讀性,也可以採取駝峯命名。如:myEclipse
函數的參數: 如果一個函數的參數名稱和保留的關鍵字衝突,可以使用一個後綴的下劃線來區分
變量: 字母數字下劃線。
函數的調用
調用函數的好處:
降低編程的難度 通常將一個複雜的問題分解爲多個小的問題而解決,以減少編程的複雜程度。
代碼重用 通常也會叫做開耦合,避免重複調用一段代碼
示例函數的調用:
>>> def add(a,b):
... print "a = ", a
... print "b = ", b
... c = a + b
... print "c = ", c
...
>>> add(1,2)
a = 1
b = 2
c = 3
>>> add(4,5)
a = 4
b = 5
c = 9
>>>
注意,這樣寫一定要注意傳遞參數的次序,如果參數太多,次序記起來很麻煩,可以直接將參數的賦值寫到調用函數的模塊兒裏面,像下面這樣:
>>> add (a = 10,b = 4)
a = 10
b = 4
c = 14
>>> add(b = 3,a = 6)
a = 6
b = 3
c = 9
>>>
也可以直接在定義函數的時候直接在參數列表中賦值,像下面這樣:
>>> def add(a,b = 2):
... print "a = ",a
... print "b = ",b
... c = a + b
... print "c = ",c
...
>>> add(3)
a = 3
b = 2
c = 5
>>> add(a = 4,b = 6) #也可以重新賦值。
a = 4
b = 6
c = 10
>>>
返回值
Python中的返回值有兩種:
返回一個值
返回多個值
具體看一下文檔:
return_stmt ::= “return” [expression_list]
return
may only occur syntactically nested in a function
definition, not within a nested class definition.
If an expression list is present, it is evaluated, else None
is
substituted.
return
leaves the current function call with the expression list
(or None
) as return value.
When return
passes control out of a try
statement with a
:
說明:”return”只能在語法上嵌套在定義的函數中,而不是被嵌套在定義的類中。
如果一個表達式列表是存在的,那麼它將會被求值計算,否則將使用“None”替代
”return”離開當前函數調用的表達式並返回值。
上面說明中,類的定義在以後將會學習,這裏只看第三個。
示例:
>>> def add(a,b):
... c = a + b
... return c
...
>>> add(1,2)
3
>>> def sub(a,b):
... c = a * b
... return c , a, b
...
>>> sub(3,9)
(27, 3, 9)
>>>
第一次接觸函數就暫時學習到這裏
完成於2017年05月17號
晚上20:30