理解函数
高中数学中,学习的函数 有一次函数,二次函数,高次函数,正余弦函数,正余切函数、指数函数、幂函数等等,都是函数。从这一节开始,学习程序中的函数。
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