博文大纲:

  • 一、函数
  • 二、变量的作用域
  • 三、内建函数

一、函数

Python中的函数都是语句和表达式的集合。和shell脚本中的函数功能一致,可以把函数当做是给一堆代码起定义了一个别名,当需要执行这堆代码时,直接调用那一堆代码集合的“别名”即可。
对于脚本中需要重复使用的代码,需要编写为自定义函数以便于重复使用。

1、无参函数

定义无参函数的语法格式如下:

def 函数名称():
    代码块
    return [表达式]

定义无参函数是以关键字def,后面跟函数名和小括号,以冒号开头并缩进,最后使用return退出函数,有表达式则传递返回值,没有则返回None。函数是以字母、数字和下划线组成的字符串,但是不能以数字开头。使用函数必须先定义再调用,否则程序会出现错误。

无参函数举例:

示例一:

#代码如下:
def add():              #定义函数
    op1 = 10
    op2 = 20
    rt = op1 + op2
    print op1, '+', op2 ,'=',rt     
    return
add()    #调用函数
#执行结果如下:
10 + 20 = 30

也可以将上面的代码进行修改,使用return语句返回结果值。

#代码如下:
def add():
    op1 = 10
    op2 = 20
    rt = op1 + op2
    return rt
i = add()         #函数返回的结果赋值给变量i
print '结果是:',i
#执行结果如下:
结果是: 30

在上面的代码中,函数add()使用return语句返回相加的结果值,变量i接收函数add()返回的值。Python在处理返回值时,如果没有return语句,会默认返回None,程序并不会报错。

示例二(九九乘法表):

#代码如下:
def mutitab():
    a = ( 1,2,3,4,5,6,7,8,9 )
    b = ( 1,2,3,4,5,6,7,8,9 )
    for op1 in a:
        for op2 in b:
            print op1 , '*',op2, '=',op1 * op2
    return
mutitab()          #调用函数
#执行结果如下:
1 * 1 = 1
1 * 2 = 2
1 * 3 = 3
1 * 4 = 4
1 * 5 = 5
1 * 6 = 6
1 * 7 = 7
1 * 8 = 8
1 * 9 = 9
#...........省略部分内容

示例二(一个简易的登陆脚本):

#代码如下:
kgc = {}
def newuser():            #注册
    prompt1 = "login desired:"
    while True:
        name = raw_input(prompt1)
        if (kgc.has_key(name)):
            prompt1 = '--name taken,try other:'
            continue
        else:
            pwd = raw_input('password:')
            kgc[name] = pwd
            break
def olduser():                     #登陆
    name = raw_input('login:')
    pwd = raw_input('password:')
    password = kgc.get(name)
    if password == pwd:
        print '--welcome back--',name
    else:
        print '--login incorrect--'
def showmenu():                 #菜单
    prompt = '''
        (N)ew User Login
        (E)ntering User Login
        (Q)uit
    Enter choice:'''
    while True:
        choice = raw_input(prompt).strip()[0].lower()
        print '\n--You piked: [%s]' %choice
        if choice not in 'neq':
            print '--invalid option,try again--'
        else:
            if choice=='n':
                newuser()
            elif choice=='e':
                olduser()
            else :
                print 'quit'
                break
if __name__== '__main__':     #程序入口,仅限于脚本执行(在这个脚本示例中,可有可无)
    showmenu()

#执行结果如下:

        (N)ew User Login
        (E)ntering User Login
        (Q)uit
    Enter choice:n            #输入n

--You piked: [n]
login desired:zhangsan            #键入一个新用户名和密码
password:12

        (N)ew User Login
        (E)ntering User Login
        (Q)uit
    Enter choice:e           #输入e

--You piked: [e]
login:zhangsan            #使用新键入的用户名和密码登录
password:12
--welcome back-- zhangsan

        (N)ew User Login
        (E)ntering User Login
        (Q)uit
    Enter choice:q

--You piked: [q]                #按q退出登录
quit

使用函数时会犯的一些错误,总结如下:

  • 函数的定义一定要先于函数的调用,否则会出错;
  • 函数体的代码是一个整体,要注意缩进;
  • 定义函数时要使用冒号,但调用时不需要冒号。

2、带参函数

定义无参函数的语法格式如下:

def 函数名称(形式参数列表):
    代码块
    return [表达式]

通过语法可以看出,带参函数和无参函数的区别是在函数名称后面的小括号有形式参数列表,参数列表实际上只是占位符,用于体现参数的个数,每个参数都没有提供具体的数值。

示例1

#代码如下:
def add(x,y):
    return x + y
print add(3,2)
#执行结果如下:
5

示例2

上一个示例中定义的形式参数是普通的参数,又称为位置参数,当调用函数时,传递的实际参数值是根据位置来跟函数定义里的参数表匹配的,如下:

#代码如下:
def add(x,y):
    print x,y
add(10,6)
add(6,10)
#执行结果如下:
10 6
6 10

示例3

当程序比较繁琐时,很容易把参数的顺序搞混,可以使用关键字参数。关键字参数是在调用函数时,指明参数赋值给哪个形参,如下:

#代码如下:
def add(x,y):
    print x,y
add(x=10,y=6)
add(y=6,x=10)
#执行结果如下:
10 6
10 6

在上面的函数aa(x,y)中,调用时明确指明了参数的名称和对应值(x=10,y=6)和(y=6,x=10),与参数所在的位置无关,明确了实参和形参的对应关系,所以输出的结果是一样的。

示例4

调用普通函数参数时,传入的参数个数必须和声明的参数个数一致,但关键字参数有一个特殊的作用,可以在定义函数时设置关键字参数的默认值,此时传入函数的参数就可以和声明的参数个数不一致了,如下:

#代码如下:
def add(x,y=4):
    print x,y
add(10)
add(x=10)
add(10,6)
add(x=10,y=6)
#执行结果如下:
10 4
10 4
10 6
10 6

在上面函数中,定义时参数y的默认值是4,调用函数时可以不传递y的值,只传递x的值即可,直接传值或使用参数名并赋值都可以,aa(10)和aa(x=10)的结果都是相同的。当传递y的值是6时,此时y的默认值不起作用,所以aa(10,6)和aa(x=10,y=6)输出时,y的值是6。

注意:定义关键字参数默认值需要注意,位置参数必须出现在默认参数之前,如下代码中函数的定义时错误的:

#代码如下
def add(y=4,x):
    print x,y
add(1,2)
#执行时,程序必然报错,所以说,默认参数必须在位置参数的后面,将y=4,放到x参数之后就可以了

示例5(综合示例)

需求如下:

  • 完成一个计算器的程序,用户输入两个数字和运算符,做加减乘除运算,
  • 为了使程序结构清晰,需要编写两个函数,一个是用来处理加减乘除运算,一个是用来处理字符串和数值转换。
#完整代码如下:
def operator(op1,op2,opfu):
    if opfu not in '+-*/':
        return -1
    if opfu =='+':
        result = op1+op2
    elif opfu =='-':
        result = op1-op2
    elif opfu =='*':
        result = op1*op2
    elif opfu =='/':
        if op2 == 0:
            print '错误,除数不能为0!/n'
            result = None
        else:
            result = op1/op2
    return result
def convert(op):
    flag = True
    for ch in op:
        if ch not in '1234567890':
            flag = False
            break
        if flag == True:
                return int(op)
        else:
            return None
if __name__=='__main__':
    str1 = '请输入第一个数:\n'
    strfu = '请输入一个算数运算符:\n'
    str2 = '请输入第二个数:\n'
    while True:
        print '需要退出程序,请输入字母q'
        opp1 = raw_input(str1)
        ch = opp1.strip()[0].lower()
        if ch == 'q':
            break
        op1 = convert(opp1)
        if op1 ==None:
            print '输入错误,请输入整数!\n'
            continue
        while True:
            opfu = raw_input(strfu)
            if opfu in '+-*/':
                break
            else:
                print '运算符输入错误'
                continue
        while True:
            op2 = convert(raw_input(str2))
            if op2 == None:
                print "输入错误,请输入整数!\n"
                continue
            else:
                break
        result = operator(op1,op2,opfu)
        if result <> None:
            print "计算%d %s %d = %d \n" %(op1,opfu,op2,result)
print '程序退出了'
#执行结果如下:
需要退出程序,请输入字母q
请输入第一个数:
10
请输入一个算数运算符:
*
请输入第二个数:
2
计算10 * 2 = 20 

需要退出程序,请输入字母q
请输入第一个数:
q
程序退出了

现在对上述代码进行分段解释:
第一段代码:

def operator(op1,op2,opfu):
    if opfu not in '+-*/':
        return -1
    if opfu =='+':
        result = op1+op2
    elif opfu =='-':
        result = op1-op2
    elif opfu =='*':
        result = op1*op2
    elif opfu =='/':
        if op2 == 0:
            print '错误,除数不能为0!/n'
            result = None
        else:
            result = op1/op2
    return result

在上面代码中,位置1处定义了函数operator(op1,op2,opfu),参数op1表示运算符前面的数值,op2表示运算符后面的数值,opfu表示运算符,然后先判断opfu是不是“+-*/”中的其中一个,如果不是,返回值是-1,表示程序出错。在接下来就是判断是哪个运算符号,就进行哪种运算处理。但是在判断除法运算符时,需要加一个条件,就是除数不能是0,因为除数是0在数学上是没有意义的,最后只要把运算的结果返回即可。

第二段代码:

def convert(op):
    flag = True
    for ch in op:
        if ch not in '1234567890':
            flag = False
            break
        if flag == True:
                return int(op)
        else:
            return None

在上面的代码中,首先定义了一个布尔型变量flag,用于判断数值的有效性,在for循环语句中,op是传进来的字符串,使用for循环判断它的每一个字符是不是在“1234567890”中,如果有一个不再,说明这个字符串不能转换为数值,flag的值为False,退出循环,否则flag的值不变,还是True,说明字符串可以转换为数值型。然后接下来做了相应的判断,把字符串op转换为了整型,使用的是int()函数。最后是如果不能转换为整型,返回的是None。

第三段代码:

if __name__=='__main__':
#以下是定义三个字符串的提示文字
    str1 = '请输入第一个数:\n'
    strfu = '请输入一个算数运算符:\n'
    str2 = '请输入第二个数:\n'
#下面是主体代码的无限循环操作,可以用来进行多次计算
    while True:
        print '需要退出程序,请输入字母q'
#以下是判断当键盘输入q时,就退出程序
        opp1 = raw_input(str1)
        ch = opp1.strip()[0].lower()
        if ch == 'q':
            break
#对输入的第一个字符串进行数值转换操作,convert()返回是None,说明不能转换,使用continue进入到下一次循环重新输入。
        op1 = convert(opp1)
        if op1 ==None:
            print '输入错误,请输入整数!\n'
            continue
#等待输入运算符,如果是“+-*/”中的一个,使用break结束循环,否则执行continue,重新输入
        while True:
            opfu = raw_input(strfu)
            if opfu in '+-*/':
                break
            else:
                print '运算符输入错误'
                continue
#下面是输入第二个数值,同样需要做转换操作,如果不能转换就需要重新输入
        while True:
            op2 = convert(raw_input(str2))
            if op2 == None:
                print "输入错误,请输入整数!\n"
                continue
            else:
                break
#下面就是调用函数operator进行运算,result不等于None就说明运算是正常的,显示出运算结果
        result = operator(op1,op2,opfu)
        if result <> None:
            print "计算%d %s %d = %d \n" %(op1,opfu,op2,result)
print '程序退出了'

二、变量的作用域

作用域是指变量在程序中的应用范围,而变量声明的位置决定它的作用域,Python按作用域区分有局部变量和全局变量。

1、全局变量:

全局变量是指在一个模块中最高级别的变量有全局作用域,除非被删除,否则存活到程序运行结束,所有函数都能访问全局变量。

2、局部变量:

局部变量是指定义在函数内的变量有局部作用域,依赖于定义变量的函数现阶段是否处于活动状态,调用函数时,局部变量产生,暂时存在,一旦函数执行完成,局部变量就不存在了。

局部变量的作用域仅限于定义它的函数,全局变量的作用域在整个模块内部都是可见的。在同一个函数中,不允许有同名的局部变量,在不同函数中,可以有同名的局部变量。在同一个程序中,全局变量和局部变量同名时,局部变量具有更高的优先级。

示例:

#代码如下:
def addage(age):
    age += 1
    print 'addage():_age=%d age=%d' %(_age,age)
    return age
_age = input('请输入年龄:\n')
rt = addage(_age)
print 'main():_age = %d'%_age
print 'main(): rt=%d' %rt
#执行结果如下:
请输入年龄:
10            #输入一个“10”
addage():_age=10 age=11
main():_age = 10
main(): rt=11

在上面的代码中,函数addage(age)中定义了局部变量age,在全局范围定义了全局变量_age。_age的值是由我们键盘输入的,它在全局都生效,所以在addage(age)函数中也可以对它进行引用。当键盘输入是10时,_age的值是10,调用“rt=addage(_age)”,就是把全局变量_age的值10传给了函数,此时addage(age)的局部变量age的值也是10,执行age += 1后,age值成为了11,而全局变量_age的值不发生变化,打印输出“_age=10 age=11”,函数的返回值age的值是11,由rt接收,所以打印“_age=10,rt=11”

通过上面的代码示例,可以看出Python采用的是值传递的方式,但实际上并不是这样。Python采用的是值传递和引用传递相结合的方式,当传递可变对象时(如字典或者列表),相当于传引用,而不可变对象(如数字、字符或元组)就是值传递。上面传递的是字符串,所以是值传递的方式。

在Python中尽量不使用全局变量,因为程序中可以自由的访问全局变量,其他人并不知道哪个变量是全局变量,非常容易出现引用错误,这种错误也很难发现和更正的。

局部变量只有在局部中才能使用,其他范围是访问不到的,如上面的代码汇总age是局部变量,在全局范围就引用不到,比如在上面程序中加上下面这行代码,就会报错。

#在上面代码末尾加上下面这段代码:
 # ....................省略部分内容
print 'main():age = %d'%age
#执行结果如下:
请输入年龄:
10
addage():_age=10 age=11
main():_age = 10
main(): rt=11

Traceback (most recent call last):     
  File "C:/Users/Administrator/Desktop/aa.py", line 9, in <module>
    print 'main():age = %d'%age 
NameError: name 'age' is not defined      #提示age没有定义

错误显示age没有定义,说明在全局范围age是访问不到的,这个问题可以使用global关键字解决,global的作用是声明变量为全局变量,即使变量定义在函数内部,加上global后,也可以在全局范围访问,修改后的代码如下:

def addage(num):
    global age
    age = num+1
    print 'addage():_age=%d age=%d' %(_age,age)
    return age
_age = input('请输入年龄:\n')
rt = addage(_age)
print 'main():_age = %d'%_age
print 'main(): rt=%d' %rt
print 'main():age = %d'%age

上面代码中做了一些调整,主要使用了global定义age,最后在全局引用age时,可以正常使用。

在函数中,使用global语句声明的全局变量名不能与其中的局部变量重名,而且尽量要避免在函数中使用global定义全局变量,减少程序的不可预知性。

三、内建函数

Python除了本身的语法结构,还提供了常用的内建函数,内建函数是我们经常使用到的方法,可增加程序编写的效率,如float()函数就是内建函数。内建函数是自动加载的,Python的解释器可以识别,它不需要导入模块,不必做任何操作,不需要引用就可以调用。

1、abs()函数能够返回一个数字的绝对值,即整数,如下:

>>> abs(10)
10
>>> abs(-10)
10
>>> bb = -3
>>> abs(bb)
3

2、bool()函数返回值是TRUE或FALSE,它是布尔值的简写,可以用来判断字符是否为空,如下:

>>> bool()    #无参数时返回False
False
>>> bool(0)
False
>>> bool(-3)
True
>>> bool(None)
False
>>> bool('xyz')
True
>>> bool('11,22')
True

3、float()函数用于转换数据为float(浮点)类型,字符串和数字都可以转换为float类型,如果不能转换,就会报错,如下:

>>> float(25)
25.0
>>> float(3)
3.0
>>> float(99.589456)
99.589456
>>> float('99.589456')
99.589456

4、int()函数可以将数据转换为整数,如下:

>>> int(199.99)     #浮点数
199
>>> int('100')     #字符串
100
>>> int('99.99')     #字符串,字符串中只能是整数格式,如果是浮点型就会报错

Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    int('99.99')
ValueError: invalid literal for int() with base 10: '99.99'

5、range()函数可以生成一个列表,如下:

>>> range(0,5)
[0, 1, 2, 3, 4]
>>> range(0,30,3)     #第三位的数字代表步长,是可选参数
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
>>> range(30,0,-3)
[30, 27, 24, 21, 18, 15, 12, 9, 6, 3]
>>> for i in range(0,5):
    print i

0
1
2
3
4

6、sum()函数可以对列表中元素求和,如下:

>>> num = range(0,500,50)   #定义一个元组
>>> num          #查看元组中的值
[0, 50, 100, 150, 200, 250, 300, 350, 400, 450]
>>> print (sum(num))    #对元组中的值进行求和操作
2250

7、max()函数可以返回列表、元组或字符串中最大的元素,如下:

>>> num = [6,2,12,7,65]
>>> max(num)
65
>>> str = 'a,d,g,c,D,U,A,N,G'
>>> max(str)
'g'
>>> max(1000,650,98,2689)
2689

8、min()函数返回列表、元组或字符串中值最小的元素,和max()正好相反,如下:

>>> min(10,9,7)
7

9、dir()函数可以返回关于任何值的相关信息,可以用于任何对象,包括字符串、数字、函数、模块、对象和类。相当于帮助手册。如下:

>>> dir()                #无参数时,返回当前范围内的变量
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '_age', 'addage', 'age', 'bb', 'i', 'num', 'rt', 'str']
>>> dir(rt)                #带参时,返回的是参数的属性、方法列表
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']

10、eval()函数是可以计算表达式的值。如下:

>>> eval('100*9')
900
>>> eval(raw_input("请输入表达式:"))
请输入表达式:8+9*2-3
23

11、len()函数返回一个对象的长度,如下:

>>> len('lvjianzhao')       #字符串
10
>>> language = ['python','java','c#','vb']       #列表
>>> len(language)
4
>>> person = {'zhangsan':'123','lisi':'234','wangwu':'345'}    #定义一个字典
>>> len(person)
3

附加——lambda函数

lambda函数的作用是创建匿名函数,是一种声明函数的特殊方式。
lambda函数的语法格式如下:

lambda params:expr

其中params相当于函数接受的参数列表,expr是函数返回值的表达式。

示例:

#代码如下
def sum1(x,y):
    return x+y
sum2 = lambda x,y:x+y
print sum1(1,2)
print sum2(1,2)
#执行结果如下
3
3

实现的是相同的功能,但lambda函数更加简洁,只用一条语句实现,所以lambda也称为lambda表达式,使用lambda只能是表达式,不能包含if、for等条件循环语句,对于不需要复用、简单的匿名函数,使用lambda能起到很好的效果。

———————— 本文至此结束,感谢阅读 ————————