Python基础之函数

函数是组织好的,可重复使用的,用来实现单一,或相关功能的代码段。 函数能提高应用的模块性,和代码的重复利用率。可以理解为对实现某一功能的封装

函数定义

定义函数遵循以下规则:

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

函数语法

def 函数名称 (可选参数):
    函数体代码
    return 返回值

函数调用

函数名(参数)

函数参数:

  • 形参:定义函数时设置的参数
  • 实形:调用函数时传入的参数

函数类型:

  • 无参无返回值函数
  • 无参有返回值函数
  • 有参无返回值函数
  • 有参有返回值函数
def x_y_sum_return(x,y):
    res = x + y
    return res

#两个实参,返回一个计算结果
z = x_y_sum_return(2,3)
print(z)


def x_y_comp_list(x,y):
    res1 = x + y
    res2 = x * y
    res_list = [res1,res2]
    return res_list
#将计算结果放在一个列表中返回,返回一个参数
print(x_y_comp_list(2,3))

def x_y_comp_tuple(x,y):
    res1 = x + y
    res2 = x * y
    res_tuple = (res1,res2)
    return res_tuple

#将计算结果放在一个元组中返回,返回一个参数
tu1 = x_y_comp_tuple(100,299)
print("tu1=",tu1)

def x_y_comp_tuple2(x,y):
    res1 = x + y
    res2 = x * y
    return res1,res2

#使用两个变量来接收元组返回的两个结果
a,b = x_y_comp_tuple2(3,6)
print("a=%d,b=%d" % (a,b))

字符串常用内置方法

中括号包起来的都是可选参数

  • find(str[, start, end]):在字符串中查找指定的子字符串是否存大,如果存在则返回第一个子字符串的起始下标,如果不存在则返回-1;start、end是可选参数,表示查找子字符串的起始和结束范围
  • count(str[, start, end]):在字符串中统计包含的子字符串的个数
  • replace(old, new[, count]):使用新的子字符串替换指定的子字符串,返回新的字符串;count是可选参数,可以指定替换的字符串个数,默认全部替换
  • split(sep[, maxsplit]):按照指定的分割符分割字符串,返回分割之后所有元素的列表;maxsplite是可选参数,指定对几人分割符进行分割
  • startswith(prefix[, start, end]):判断字符中是否以指定前缀开头,返回值为True或False;start、end是可选参数,表示查找 前缀的起始和结束范围
  • endswith(suffix[, start, end]):判断字符中是否以指定后缀结束,返回值为True或False;start、end是可选参数,表示查找后缀的起始和结束范围
  • upper():字符串所有字符大写
  • lower():字符串所有字符小写

变量

Python中,程序的变量并不是在任何位置都可以访问的,具体从哪个位置可以访问,取决于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。

Python的作用域一共有4种,分别是:

  • L(Local) 局部作用域
  • E(Enclosing)闭包函数外的函数中
  • G(Global)全局作用域
  • B(Built-in)内建作用域

以上作用域范围按L->E->G->B的规则查找,即:在局部找不到,变回去局部外的局部找(例如闭包),再找不到就回去全局找,再者去内建找。

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

局部变量

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

  • 函数内部定义的变量
  • 不同函数内的局部变量可以定义相同的名字,互不影响
  • 作用范围:函数体内有效,其他函数不能直接会使用
#这里在set_name和get_name重定义的name都属于局部变量,只能从函数体内部访问
def set_name():
    name = "zhangsan"
    return name

def get_name(name):
    print(name)

nm = set_name()
print("nm={}".format(nm))
get_name("susan")
全局变量

全局变量从函数体外定义,可以在不同的函数中使用,属于全局型变量

  • 函数外部定义的变量
  • 作用范围:可以在不同函数中使用
  • 在函数内使用global关键字实现修改全局变量的值
  • 全局变量命名建议以g_开头,如:g_name
  • 全局变量定义的位置:函数调用之前定义
#函数体外定义的name变量,为全局变量,无论从函数内访问,还是函数外访问,都是一样的
name = "zhangsan"
def get_name():
    print(name)

def get_name2():
    print(name)

get_name()
get_name2()
print(name)

函数参数(缺省参数、不定长参数、命名参数)

缺省参数

定义函数形参的时候,可以指定缺省值,形如: def fun(x=10,y=20)

  • 函数定义带有初始值的形参
  • 函数调用时,缺省参数可传,也可不传
  • 缺省参数一定要位于参数列表的最后
  • 缺省参数的数量没有限制
#定义函数x_y_sum,并指定形参y的缺省值为20
def x_y_sum(x, y = 20):
    print("x=%d" % x)
    print("y=%d" % y)
    return x + y


rs1 = x_y_sum(10, 20)
print("rs1=", rs1)
#调用的时候形参y对应的实参缺省,则取默认值
rs2 = x_y_sum(10)
print("rs2=", rs2)
#定义的时候形参y对应的实参指定为30,则y取值为指定的30
rs3 = x_y_sum(10, 30)
print("rs3=", rs3)
不定长参数

很多时候,一个函数调用的参数事先我们并不知道,这个时候就可以使用不定长参数

  • 函数可以接收不定个数的参数传入
  • def function([formal_args,]*args)函数调用时,传入的不定参数会被封装成元组
#定义一个函数,函数中包含了接收不定长参数的*args,函数内对不定长参数进行处理
def any_num_sum(x, y=10, *args):
    print("args={}".format(args))
    rs = x + y
    if len(args) > 0:
        for arg in args:
            rs += arg
    return rs
rss = any_num_sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print("rs={:d}".format(rss))
  • def function([formal_args,]**args)函数调用时,如果传入key=value形式的不定参数会被封装成字典
#使用列表和字典格式接收的时候,形参列表中*argu在前,**kwargu在后
def social_insurance_comp(basic_money, *staff, **proportion):
    print(proportion)
    print(staff)
    e_money = basic_money * proportion["e"]
    m_money = basic_money * proportion["m"]
    a_money = basic_money * proportion["a"]
    total_money = e_money + m_money + a_money
    for item in staff:
        print("item=%s" % item)
    return total_money
#当实参和形参结合的时候,列表实参变量在前,字典实参变量在后,顺序不能发生错误
sum_1 = social_insurance_comp(1000, "zhangsan", "lisi", "wangwu", e=0.2, m=0.1, a=0.05)
print("sum={}".format(sum_1))
命名参数

命名函数,即在调用函数的时候,指定名称的实参,实参名称与函数定义时的形参要相同,但是顺序可以不同

  • 调用带有参数的函数时,通过指定参数名称传入参数的值
  • 可以不按函数定义的参数顺序传入
def x_y_sum(x=10,y=20):
    return x+y
#用命名参数调用,指定调用实参要结合的形参名
rs1 = x_y_sum(y=50,x=100)
#用命名参数调用,只指定了x,y没指定,缺省
rs2 = x_y_sum(x=15)
#x,y都缺省
rs3 = x_y_sum()
print("rs1=%d" % rs1)
print("rs2=%d" % rs2)
print("rs3=%d" % rs3)
拆包

对于定义 了不定长参数的函数,在函数调用时需要把已定义好的元组或者列表传入到函数中,需要使用拆包方法

def salary_comp(basic_money, *other_money, **proportion):
    print("缴费基数:{}".format(basic_money))
    print("其他工资:{}".format(other_money))
    print("比例:{}".format(proportion))


other_money = (500, 200, 100, 1000)
proportion_dict = {"e": 0.2, "m": 0.1, "a": 0.12}
#在这种调用形式下,other_money和proportion_dict被当做一个列表参数提提供给了*other_money,则结果只能是列表和词典作为一个元组传入
salary_comp(8000, other_money, proportion_dict)

递归函数及应用

函数调用自身,其典型应用为求阶乘:

def recursive(num):
    if num > 1:
        return num * recursive(num-1)
    else:
        return 1


print('{}'.format(recursive(4)))

注意:递归过程中要有用于结束递归的条件判断
range(1,num) 是左闭右开的

匿名函数及应用

用lambda关键字创建匿名函数,其实质为没有名称的函数
定义:lambda [参数列表]:表达式
匿名函数可以作为参数被传入其他函数

def x_y_comp(x,y,func):
    rs = func(x,y)
    print(rs)

#在传入参数的时候,指定函数的功能为加法    
x_y_comp(3, 5, lambda x,y:x+y)
print("---")
#在传入参数的时候,指定函数的功能为减法
x_y_comp(10, 6, lambda x, y:x-y)