python基础:函数

一.函数基本语法及特性

1、背景提要

现在老板给你两组数据需要你写一个算法程序来计算他们之间的和,

例如:14和89, 45和86

(妈的,这么简单的算法自己不算,不会按计算机?)你掏空了所有的知识量,写出了以下代码

a = 14
b = 89
sum = a+b
print('%s + %s ='%(a,b),sum)

c = 45
d = 86
sum = c+d
print('%s + %s ='%(c,d),sum)

输出:
14 + 89 = 103
45 + 86 = 131

愚蠢的老板发现给的数据都能算出正确的答案,也看不出问题,于是又给了几组数据需要你计算。MD,又需要复制粘贴代码吗,嘴上说好好好,你又回家改代码去了。

串门的热心邻居老王看到你回来就不是很高兴了,而且还一直在那里复制粘贴,浪费时间不说,你老婆孩子还看着累。说着帮你看看代码怎么写的。

老王不愧是老司机,发现上面的代码虽然实现了功能,但问题很多啊,老王亲切的摸了下你家儿子的脸蛋,说,你这个重复代码太多了,每次拿到一组数据都要重写一遍相加并输出的代码,太low了。于是热心的老王帮你整理出了两个问题:

  1. 代码重复过多,不符合高端程序员的气质
  2. 可修改行太差,后面可能加法变乘法,需要一个一个修改

你觉得老王说的对,你也不想写重复代码,但又不知道怎么搞,老王好像看出了你的心思,此时他抱起你儿子,笑着说,其实很简单,只需要把重复的代码提取出来,放在一个公共的地方,起个名字,以后谁想用这段代码,就通过这个名字调用就行了,如下

def sum(x, y):
    sum = x + y
    print('%s + %s ='%(x,y),sum)

a = 14
b = 89
c = 45
d = 86
sum(a,b)
sum(c,d)

你看着老王写的代码,气势恢宏、磅礴大气,代码里透露着一股内敛的傲气,老板看到这样的代码,会不会给我涨工资呢,明天得跟老板商量商量

2、函数是什么?

函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,具体区别,我们后面会讲,编程中的函数在英文中也有很多不同的叫法。在BASIC中叫做subroutine(子过程或子程序),在Pascal中叫做procedure(过程)和function,在C中只有function,在Java里面叫做method。

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

特性:

  1. 减少重复代码
  2. 使程序变的可扩展
  3. 使程序变得易维护

语法定义

# def 函数名():
#     函数体
#
# 函数名()

def function(): # 函数名
    # 函数体:函数要实现的内容
    print('我是函数')

function() # 调用函数

可以带参数

def sum(x, y):
    sum = x + y
    print('%s + %s ='%(x,y),sum)

a = 14
b = 89
sum(a,b)

二.函数参数与局部变量  

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

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

1、默认参数

例如我们在填写个人信息的时候有一个国籍的选项,当然我们都是选中国了(默认都是国人),但每个人都写一遍,是不是感觉重复呢?

def userInfo(name, age, country):
    print(name, age, country)

userInfo('zhang', 18, 'CN')
userInfo('li', 28, 'CN')
userInfo('zhu', 22, 'CN')

发现 country 这个参数 基本都 是"CN", 所以我们去招聘或者填写一些个人信息的时候,都不会出现国籍这个表格填写项,默认就会是 中国, 这就是通过默认参数实现的,把country变成默认参数非常简单

def userInfo(name, age, country='CN'):
    print(name, age, country)

userInfo('zhang', 18)
userInfo('li', 28)
userInfo('zhu', 22)

这样,这个参数在调用时不指定,那默认就是CN,指定了的话,就用你指定的值。

2、关键参数

正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可,但记住一个要求就是,关键参数必须放在位置参数之后。

 

3、非固定参数

当你的函数是一个可以接收很多参数的时候(很多是指你懒得敲的次数),可以使用非固定参数*args进行接收

还可以有一个**kwargs

可以发现不传参时,**kwargs默认是一个空的字典{}(当然是因为你没有传参了),我们试试传参

 

全局与局部变量

在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。

全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。

当全局变量与局部变量同名时:

在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。

 打个比方:

每个家庭是一个函数,你老婆是你老婆,我不可能带走你老婆。但是存在老王这样的热心邻居,当老王去访问你家,并想将你老婆娶回自己家的时候。当然不行啦,法律不允许,在代码程序里面直接就报错了。老王能带回家的也只有那些没有组家庭的女性。

老婆=局部变量,只能函数内调用。

没组家庭的女性=全局变量,大家都可以调用。

下面上代码:

noMarry = 'li'

# 这是朱家,男主人有个妻子姓赵,这个男人比较开放,可以放妻子出去玩(return)
def zhuHome():
    man = 'zhu'
    wife = 'zhao'
    return wife
    
laowang = "老王"
# 老王想找wife一起跑步,但不能直接就使用wife, 而是需要通过调用函数, 并且函数内有return数据
# print('%s找%s一起跑步' %(laowang, wife)) # 这样直接报错了,因为wife是局部变量
print('%s找%s一起跑步' %(laowang, zhuHome()))
print('%s找%s一起跑步' %(laowang, noMarry)) # 但是老王可以直接找没结婚的人一起跑步,因为noMarry是全局变量

三.返回值return  

要想获取函数的执行结果,就可以用return语句把结果返回

注意:

  1. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
  2. 如果未在函数中指定return,那这个函数的返回值为None 

举个例子:

你知道古代帝皇如何知道外敌入侵么?就是在关外(边界)有一个高高筑起的高塔,或者是山顶上有一个烽火台,只要有外敌,则就会有人点燃烽火台进行传递信息,当然了,烽火台一段一段距离有分布,皇帝才能收到消息。但是在城内是不可能有烽火台的(假设),在最后一个烽火台到城内是通过快马加鞭去传达消息的。那么我们来写写这段烽火传情(情当然是情报的意思了)

我们假设只有两个烽火台,还有一匹马

def fenghuotai_1():
    print('有情况,点火了,火很大')

def fenghuotai_2():
    print('有情况,点火了,火也是很大')

# 情况一:有返回内容,即报告书上有内容
def mapi_1():
    info = "敌人入侵"
    return info
    # 发现报告书上写的内容不详细,于是重写
    info = "发现烽火台烽烟四起,有敌人入侵"
    return info  # 此时再次return已经没用了,因为只有一匹马(第一次return,后面的语句都不会执行)

# 情况二:没有返回内容,即报告书上没有
def mapi_2():
    info = "敌人入侵"

# 假设我看到了外敌入侵,我去点火
fenghuotai_1()  # 因为点完火就没事做了,也就是没有return数据过来
# 离皇宫较近的地方,发现远处烽火点燃了,则马上点燃
fenghuotai_2()
# 离皇宫最近的一个点,发现最近的烽火台点燃了,由不是烽火台只能速速写了报告书,则马上骑马上京
huangdi = mapi_1() # 谁得到消息呢?当然要选一个人去接收报告书啦,(需要一个变量去获得该函数的返回值)就得到外敌入侵的消息
print(huangdi)
huangdi = mapi_2() 
print(huangdi)

四. 常用函数

1、嵌套函数

# 假设一个家、一个房间相当于一个函数,那我家很大哦,可以有多个房间哦
# 于是乎
def home():
    def room():
        print('来到房间')

    print('来到我的家')
    # 通过调用,才能进去房间
    room()
    
# 嵌套函数也有区分局部变量,即home里面的局部变量和room里面的局部变量,具体细节请在群内讨论

home()

2、递归函数

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

1. 必须有一个明确的结束条件

2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

# 比如:男子汉打篮球就是要打到体力不支,假设体力不支为能量为0,energy=0
def playBall(n): # 输入你的体力
    print(n)   # 输出玩的体力
    if int(n) <= 0:  # 有一个明确的结束条件
        return '请回家'
    # 每次体力减2
    n -= 2  # 每次递归,体力都会减少
    return playBall(n)


playBall(10)

3、匿名函数

难搞哦!!!取名字好麻烦哦!!!那就用匿名函数吧

#这段代码
def calc(n):
    return n**n
print(calc(10))
 
#换成匿名函数
calc = lambda n:n**n
print(calc(10))

4、高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

def add(x,y,f):
    return f(x) + f(y)
 
 
res = add(3,-6,abs)
print(res)

 

有什么问题请指教

欢迎添加微信号ZFQuan203,进群一起学习,有问题一起讨论

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值