Python【第三课】 函数基础

本篇内容

  1. 函数基本语法及特性

  2. 嵌套函数

  3. 递归函数

  4. 匿名函数

  5. 高阶函数
  6. 内置函数

1.函数的基本语法及特性

1.1 函数概念

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

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

特性:

  1. 减少重复代码

  2. 使程序变的可扩展

  3. 使程序变得易维护

1.2 函数的定义

你可以定义一个由自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

语法:

Python 定义函数使用 def 关键字,一般格式如下:

def 函数名(参数列表):
    函数体

例1:

通过调用函数名,执行函数:

def sayHi():
    print("hello word!")
sayHi()
# 输出
hello word!

例2:

输出前n个数的偶数和,需要用户给函数传递一个参数。

def sum(num):
    a=0
    for i in range(num):
        a += i+1 if (i+1)%2 == 0 else 0
    return a
print(sum(100))

# 输出
# 2550

函数调用:

定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。

这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。

如下实例调用了 prinmsg() 函数:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

# 定义函数
def printmsg(msg):
    '''
    打印传入的字符串
    '''
    print(msg)
    return

# 调用函数
printmsg("hello world!")
printmsg("hello,40kuai!")
# 输出
hello world! hello,40kuai!

1.3 参数

1.3.1 实参和形参

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

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

 

1.3.2 参数类型

以下是调用函数时可使用的正式参数类型:

  • 必需参数
  • 关键字参数
  • 默认参数
  • 不定长参数

必需参数

必需参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

调用printmsg()函数,你必须传入一个参数,不然会出现语法错误:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def printmsg(msg):
    '''
    打印传入的字符串
    '''
    print(msg)
    return
printmsg()

  

# 输出
Traceback (most recent call last): File "C:/Users/helei/PycharmProjects/S16/day3/test.py", line 10, in <module> printmsg() TypeError: printmsg() missing 1 required positional argument: 'msg'

关键参数

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

以下实例在函数 printmsg() 调用时使用参数名

正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可

def printmsg(msg,num):
'''
打印传入的字符串
'''
print(msg)
print(num)
return
printmsg(num=12,msg="hello world")
# 输出
hello world!
12    
# 不按顺序传入关键参数不影响输出结果。

但记住一个要求就是,关键参数必须放在位置参数之后。

# 如果关键参数在位置参数之前
def printmsg(msg,num): ''' 打印传入的字符串 ''' print(msg) print(num) return string="hello world!" printmsg(num=12,string)
#输出如下报错信息
File "C:/Users/helei/PycharmProjects/S16/day3/test.py", line 12 printmsg(num=12,string) ^ SyntaxError: positional argument follows keyword argument

正确的应该为:


def printmsg(msg,num): ''' 打印传入的字符串 ''' print(msg) print(num) return string="hello world!" printmsg(string,num=12) # 输出 hello world! 12

默认参数

在定义函数时,可以把函数的参数定义为默认参数,如下

def msg(name,age=22):
    print('name:',name)
    print('age:',age)

在调用带有默认参数的函数时,用户可以不给默认参数赋值,当不赋值时,变量使用默认的参数。

msg('40kuai')
msg('40kuai',40)
# 输出
# name: 40kuai
# age: 22
# name: 40kuai
# age: 40

不定长参数

若函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数,先来看下*args的效果

def msg(msg,*args):
    """
    打印输入的所有字符串
    """
    print(msg)
    for i in args:
        print(i)


msg('name',11,22,33,44)
# 输出
# name
# 11
# 22
# 33
# 44

好像不太直观,那就让你看看args中是什么数据:

def msg(msg,*args):
    """
    打印输入的所有字符串
    """
    print(msg)
    print('args:',args)
    for i in args:
        print(i)
msg('name',11,22,33,44)
# 输出
# name
# args: (11, 22, 33, 44)
# 11
# 22
# 33
# 44

再来看看还有一个**kwargs:

def msg(msg,*args,**kwargs):
    """
    打印输入的所有字符串
    """
    print(msg)
    print('args:',args)
    print(kwargs)
    # for i in args:
    #     print(i)
msg('name',11,22,33,44,name='40kuai',age=18)
# 输出
# name
# args: (11, 22, 33, 44)
# {'name': '40kuai', 'age': 18}

看了这么多总结一下

默认参数放到位置参数的后面

关键字参数放到必需参数的后面

关于*args和**kwargs

*args的作用就是把用户多余输入的(位置)参数,放到args中,以元组的形式。

**kwargs的作用是把用户多余输入的(关键)参数,放到kwargs中 ,以字典的形式保存

1.4 函数的返回值

return [表达式] 的作用有两方面:

1.用于退出函数

2.选择性地向调用方返回一个表达式。

  不带参数值的return语句返回None。(0,None,空的返回值为False)

  可以返回多个值,以元组形式返回

1.5 变量作用域

Pyhton 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。两种最基本的变量作用域如下:

  • 全局变量
  • 局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

name  = '40kuai'
def put(name):
    print("美男子:",name)
    name = '还是我'
    print("美男子:", name)

print("美男子:", name)
put(name)
print("美男子:", name)

输出结果:

美男子: 40kuai
美男子: 40kuai
美男子: 还是我
美男子: 40kuai

2.嵌套函数

哎,我也忘了,先来个代码想想。

string = 'hello world!'
def msg():
    print("msg")
    def msg1(st):
        print(st)
msg()

# 输出
# msg

函数里边套个函数,就是嵌套函数。哈哈哈哈

但是为什么没有输出第二次函数的结果呢,恩~,没调用。再试试

string = 'hello world!'
def msg():
    print("msg")
    def msg1(st):
        print(st)
msg()
msg1()

# 输出
# msg
# NameError: name 'msg1' is not defined

报错了,想起来了,函数就是相当于变量,定义到函数内部就是局部变量,在全局当然找不到,我真聪明。

string = 'hello world!'
def msg():
    print("msg")
    def msg1(st):
        print(st)
    msg1("string")
msg()

# 没毛病

但是就想在外边调用内部函数怎么办。再想想~~

string = 'hello world!'
def msg():
    print("msg")
    def msg1(st):
        print(st)
    return msg1
msg1 = msg()
msg1("string")

# 就要变身为装饰器了,后面讲 

3.递归函数

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

date = range(4200000000)
count = 0
def search(find_num, date, count):
    mit = int(len(date)/2)
    num = date[mit]
    if find_num > num:
        print('',count,num)
        search(find_num, date[mit:],count+1)
    elif find_num < num:
        print('',count,num)
        search(find_num,date[:mit],count+1)
    else:
        print(count,num)

search(123456,date,count)
二分查找

递归特性:

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

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

3. 递归效率不高,递归层次过多会导致栈溢出(最大的递归层数为999层)

4.匿名函数

 匿名函数就是不需要显式的指定函数

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

copy:你也许会说,用上这个东西没感觉有毛方便呀, 。。。。呵呵,如果是这么用,确实没毛线改进,不过匿名函数主要是和其它函数搭配使用的呢,如下

res = map(lambda x:x**2,[1,5,7,4,8])
for i in res:
    print(i)

5.高阶函数

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

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

6.内置函数

 

内置函数使用方法,后续补上。。。。有人提醒我吗?

最新内容可以看我的blog: 40kuai
原文地址:https://www.cnblogs.com/40kuai/p/6374356.html