您的浏览器不兼容canvas

(十三)函数基础

函数

定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

为什么要用函数

1、代码的组织结构不清晰,可读性差
2、遇到重复的功能只能重复编写实现代码,代码冗余
3、功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护难度极大

函数的分类

主要分两类,内置函数和自定义函数

  • 内置函数
    python解释器事先为我们内置好的函数以便实现简单功能。拿来就用,无需事先定义。比如len(), sum(),type()

image

  • 自定义函数
    内置的函数很有限,大多数的时候需要我们根据自己的需求,进行自定义函数来实现某种功能,在以后用的时候,直接调用。

例如

def calc(x,y):
    res=x*y
    # print(res)
    return res
c=calc(5,8)
print(c)
定义函数

一、 如何定义函数

语法:
def 函数名(参数1,参数2...):
    '''注释'''
    函数体
    return 返回值

二、函数的使用原则

先定义,在调用

 def foo():
   print('from foo')
   bar()

foo()

>>>NameError: name 'bar' is not defined



def foo():
   print('from foo')
   bar()
def bar():
   print('from bar')

foo()


>>>from foo
>>>from bar

我们在使用函数时,一定要明确区分定义阶段和调用阶段

函数在定义阶段,只检查语法,逻辑错误只有在调用阶段才知道。

定义函数的三种形式
  • 无参: 仅仅是执行一些操作,比如用户交互,打印
  • 有参:函数体依赖于外部传入的参数,比如求最大值最小值。
  • 空函数: 编程初期,仅仅是为了设计代码结构,函数体通常为pass
无参
def msg():
    print('this is bruce')
msg()


支付系统
def msg():
    print(tag1()*35)
    print(tag2()*10,'welcom to ATM',tag2()*10)
    print(tag1()*35)
def tag1():
    return "*"
def tag2():
    return "="

def pay():
    print('from pay')

def check():
    print('from check')

def transfer():
    print('from transfer')

def likai():
    return quit()

while True:
    def run():
        print('''
        1 支付
        2 检查
        3 交易     
        4 退出  
        ''')
        choice=input('please select one>>> ').strip()
        if choice=='1':
            pay()
        elif choice=='2':
             check()
        elif choice=='3':
             transfer()
        elif choice=='4':
             likai()
        else:
            print('please retry,{} times left' .format(retry))
    run()




有参
def max(x,y):
    if x>y:
        return x
    else:
        return y
res=max(5,8)
print(res)

>>>8


def tag(tag,n):
    print(tag*n)
def msg():
    print('hello brother')

tag("*",15)
3msg()
tag("*",15)

>>>
***************
hello brother
***************



调用函数

如上例所示,函数是通过函数名加括号调用,

其实,函数调用有三种形式

  • 语句形式: msg()
  • 表达式形式:3*len()
  • 当做另外一个函数的参数
函数返回值

return 是函数结束的标志,函数内可以有多个return,但是只要执行一个,函数就结束。而且把return的值当做本次调用的结果返回。

返回值没有类型限制,可以是任意类型。

def max2(x,y):
   if x>y:
       return [1,2,3,4]
   else:
       return  {'a':8,'b':4,'c':0},'hello,workd',18,['a',1,{'t':1}]
print(max2(1,2))

>>>({'a': 8, 'b': 4, 'c': 0}, 'hello,workd', 18, ['a', 1, {'t': 1}])

一般手工指定return,如没有指定,则返回None

return 1个值-->返回1个值

return逗号分隔多个值,返回值是元组,见上例

({'a': 8, 'b': 4, 'c': 0}, 'hello,workd', 18, ['a', 1, {'t': 1}])

什么时候该有返回值?

调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值

    
通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果

什么时候不需要有返回值?

调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值

通常无参函数不需要有返回值

函数的参数

分为两大类

  • 形参
    变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量

  • 实参
    可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

  1. 位置形参:定义函数的时候,按照从左到右的顺序依次定义的形参,叫位置形参,位置形参必须被传值,多一个不行少一个也不行

  2. 位置实参: 在调用函数时,按照从左到右的顺序依次传入的值,称为位置实参,位置实参与形参一一对应

def foo(x,y,z):
    print(x,y,z)


 foo(1,2,3)
 foo(1,2)
 foo(1,2,3,4)

  1. 默认形参: 在函数定义阶段,就已经被赋值的参数,称为默认形参,比如contry='CN'。默认参数的值应该设置成不可变类型(字符串,数字,元组)

    在调用阶段可以不赋值而采用默认值。如果赋值则采用新值。默认参数只有在定义阶段被赋值一次就固定死了,定义之后的改变不受影响。

def ailen (x,y,z=10):
    return x,y,z

print(ailen(1,2,3))

>>>(1, 2, 3)

def ailen (x,y,z=10):
    return x,y,z

print(ailen(1,2))

>>>(1, 2, 10)

m=10
def foo(x,y=m):
    print(x)
    print(y)
m=111               #不受影响
foo(1)

>>>1
>>>10

  1. 关键字实参: 在函数调用阶段,采用key=value形式定义的实参,称为关键字实参。可以完全打乱顺序,相当于指名道姓的为形参传值。

    位置实参可以和关键字实参混合使用,一定要放到位置参数的后面,且同一形参只能被赋值一次。

def ailen (x,y,z):
    print(x,y)
ailen(1,2,3)

 ailen(1,2,3,4)  #报错 没有一一对应

ailen(1,y=4,z=2)
ailen(1,y=4,x=2)  #报错,x被赋值两次。

学生注册信息


def stu_register(name,age,course,contry='CN'):
    print('注册信息')
    print('姓名',name)
    print('年龄',age)
    print('国籍',contry)
    print('课程',course)
stu_register('bruce',22,'python')
stu_register('peter',32,'CN','linux')
stu_register('elaine', 18,'CN','English')


>>>
注册信息
姓名 bruce
年龄 22
国籍 CN
课程 python
注册信息
姓名 peter
年龄 32
国籍 linux
课程 CN
注册信息
姓名 elaine
年龄 18
国籍 English
课程 CN
非固定参数

若你的函数在调用时不确定用户想传入多少个参数,就可以使用非固定实参,实参无非两种形式,1. 位置实参,2. 关键字实参, 所以对应的,形参也必须有两种解决方案,专门用于接收溢出的位置实参和关键字实参。

形参中用 * 接收位置实参,存成元组形式,然后赋值给后面的变量。

def foo(x,y,*z):
    print(x,y,z)
foo(1,2,3,4,5)

>>>1 2 (3, 4, 5)

实参中用 * 传递值给形参

def func(x,y,*z):
    print(x,y,z)
func(1,2,*(3, 4, 5))
func(1,2,*[3, 4, 5])
func(1,2,*'345')

>>>
1 2 (3, 4, 5)
1 2 (3, 4, 5)
1 2 ('3', '4', '5')


形参中用 ** 接收关键字实参,存成字典形式,然后赋值给后面的变量

def foo(x,y,**z):
    print(x,y,z)

foo(1,2,z=4,a=5)

>>>1 2 {'z': 4, 'a': 5}

实参中用 ** 传递值给形参

def func(x,y,**z):
    print(x,y,z)
func(1,2,**{'z':3,'a':4,'b':5})

>>>1 2 {'z': 3, 'a': 4, 'b': 5}

更多的时候,按照python界俗称的约定,用*args 代表*z,用**kwargs代表**z

def bruce(*args,**kwargs):
    print(args)
    print(kwargs)
bruce(1,2,3, x=100,y=200)

>>>
(1, 2, 3)
{'x': 100, 'y': 200}
练习题

1、写函数,,用户传入修改的文件名,与要修改的内容,执行函数,完成批了修改操作



def modify_file(filename,old,new):
    import os
    with open(filename,'r',encoding='utf-8') as read_f, \
            open('.bak','w',encoding='utf-8') as write_f:
        for line in read_f:
            if old in line:
                line=line.replace(old,new)
            write_f.write(line)

    os.remove(filename)
    os.renames('.bak',filename)

modify_file('access.txt', 'a','1')

2、写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数

def check_str(msg):
    dic={
        'digit':0,
        'letter':0,
        'space':0,
        'other':0
        }
    for s in msg:
        if s.isdigit():
            dic['digit']+=1
        elif s.isalpha():
            dic['letter']+=1
        elif s.isspace():
            dic['space']+=1
        else:
            dic['other']+=1
    print(dic)

check_str('jaldsjfelsajdlf32 12123 zd  9')

3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。

def checklen(msg):
    if len(msg)>5:
        print('YES')
    else:
        print('NO')

checklen([1,2,3,4,5])

4、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

def len_check(msg):
    if len(msg)>2:
        return (msg[0:2])

print(len_check(['a,b,c,d,e','b','c']))

5、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。

def in_check(msg):
    return msg[::2]
print(in_check([1,2,3,4,5,6]))

posted @ 2018-04-26 11:46  Morron  阅读(152)  评论(0编辑  收藏  举报