python函数详解

函数定义

  • 格式
# 格式
# def 函数名(num):
#     pass
# 调用函数:
# 函数名(num)
  • 函数定义实例:
def caculateNum(num):
    """
    计算1~num质检的累加和
    :param num:累加和的末尾
    :return: 返回累加和
    """
    res = 0
    for i in range(1,num+1):
        res += i
    return res

res = caculateNum(100)
print(res)

5050

三种传参方式

  • 按位置顺序传参
def get_fullname(first_name,last_name='凌宇'):
    full_name = first_name+last_name
    return full_name
full_name = get_fullname('李','诗才')
print(full_name)

李诗才

  • 按关键字传参,参数顺序可以任意
def get_fullname(first_name,last_name='凌宇'):
    full_name = first_name+last_name
    return full_name
full_name = get_fullname(last_name='诗才',first_name='李')
print(full_name)

李诗才

  • 默认传参
    当参数缺省时,默认参数会生效,默认参数需要在函数声明时指定其值,如果传参时省略了默认参数,则该参数的值为默认值。如下函数中的last_name
def get_fullname(first_name,last_name='凌宇'):
    full_name = first_name+last_name
    return full_name
full_name = get_fullname(first_name='李')
print(full_name)

李凌宇

“*”操作符

将参数放置到一个元组中

def self_print(name,*a):
    print(name)
    print(type(name))
    print(a)
    print(type(a))
self_print(1,2,3,4,5,6)

1
<class 'int'>
(2, 3, 4, 5, 6)
<class 'tuple'>

1被赋值给了name,后面的2,3,4,5,6放置到元组中

注意:*操作符也可以拆开元组或列表
效果如下:

# * 有拆开元组、列表的作用
t = (1,2,3,4,5)
print(*t)

1 2 3 4 5

所以以上代码可以改成如下:

def self_print(name,*a):
    print(name)
    print(type(name))
    print(a)
    print(type(a))
self_print(*(1,2,3,4,5,6))

1
<class 'int'>
(2, 3, 4, 5, 6)
<class 'tuple'>

“**”操作符

把参数都放入到字典中

def d_self_print(**kwars):
    print(kwars)
d_self_print(first_name="li",last_name="shicai")

{'first_name': 'li', 'last_name': 'shicai'}

注意:“**”操作符如果作用于字典,可以将一个字典拆开所以上面代码可以和下面这种写法等效

# ** 有拆开字典的作用
def d_self_print(**kwars):
    print(kwars)
d_self_print(**{'first_name': 'li', 'last_name': 'shicai'})

{'first_name': 'li', 'last_name': 'shicai'}

return

用于返回值,可以用“,”分割,代表一个元组

def sum_and_avg(*numbers):
    total = sum(numbers)
    avg_number = total/len(numbers)
    return total,avg_number
sum,avg = sum_and_avg(1,2,3,4,5,6,7,8,9,10)
print("总和是%f"%(sum))
print('平均值是%f'%(avg))

总和是55.000000
平均值是5.500000

函数的传参问题

参数分为引用类型,普通类型,python中的基本数据类型都是普通类型。包括数、布尔、字符串型,除了这些之外的都是引用类型。普通类型赋值的时候传的是值;引用类型赋值的时候,传的是址

l1 = [1,2,3,4,5,]
l2 = l1
l2[1] = 5
print(l1)

a = 5
b = a
b = 10
print(a)

[1, 5, 3, 4, 5]
5

上面列表传的是列表的地址,是引用,而b=a的操作是传的值

传参的本质就是赋值操作,如果传递的引用数据类型,则需要注意是否在函数中对其做出了修改
为了防止在函数中修改了值,通常会创建一个数据副本

def power(numbers):
    # 列表推导式可以创建一个副本,不改变原本的值,
    # 函数中的numbers与外部的number不是同一个number,只是值相同,但地址不同
    # numbers = [x**2 for x in numbers]

    # 也可以赋值创建副本,不改变原本的值
    # numbers = numbers[:]
    # numbers = list(numbers)
    numbers[3] = 10
    return numbers
nums = [1,2,3,4,5,6,7,8,9,10]
print(power(nums))
print(nums)

函数的本质

函数的本质其实是地址

def fun():
    print("hello world!")

# 函数名的本质是函数的地址
f = fun
print('f即函数的地址:', f)
f() # 效果等同于fun()

f即函数的地址: <function fun at 0x000001B512E5C1E0>
hello world!

函数的闭包

即函数的嵌套在函数内部还可以定义一个函数,例子包含在下面变量的讲解中。

函数变量的作用域

python中,变量的作用域是以函数为单位的,内层函数可以访问外层函数的变量,但是不能修改

def outter():
    a = 10
    def inner():
        a = 20
        print('内层',a)
    print('外层未改变',a)
    return inner
outter()()

外层未改变 10
内层 20

  • global:加了global表示调用的时全局变量,即最外层变量,而不是当前函数或者外层函数所创建的
a = 5
def outter():
    a = 10
    def inner():
        global a # 用了global后,与全局a是同一个,并非副本
        print('内层赋值前',a)
        a = 20
        print('内层赋值后',a)
    inner()
    print('外层函数的变量不变',a)
outter()
print('最外层全局变量因内层赋值后而改变',a)

内层赋值前 5
内层赋值后 20
外层函数的变量不变 10
最外层全局变量因内层赋值后而改变 20

  • nolocal
    nolocal修饰变量时,说明使用的嵌套层函数的变量,内层函数访问变量时会先从自己查找,如果找不到,就会层层向上查找
a = 5
def outter():
    a = 10
    def inner():
        nonlocal a # 用了global后,与全局a是同一个,并非副本
        print('内层赋值前',a)
        a = 20
        print('内层赋值后',a)
    inner()
    print('外层函数的变量改变',a)
outter()
print('最外层全局变量不变',a)

内层赋值前 10
内层赋值后 20
外层函数的变量改变 20
最外层全局变量不变 5

总结:变量通常只作用于当前函数体内,若内层函数有同名变量,其实只是外层函数变量的副本,改变内层函数变量的值,并不改变外层函数变量的值;但加了global或nolocal关键字修饰后的变量则不同,内层函数变量不再是副本,用global修饰的内层函数变量就是全局变量,nolocal修饰的变量层层向上查找,改变内层函数变量的值即改变的外层的值。类似于传址。

函数的递归

所谓递归,就是自己调用自己,编写递归函数时,一定要注意出口的设置,否则函数会无线调用下去;并且可以用递归解决的问题一定可以用循环解决。不多说,直接上个阶乘的例子

def factorial(n):
    mm = 1
    for num in range(1,n+1):
        mm *=num
    return mm

print(factorial(5))
def factorial1(n):
    if n== 1:
        return 1
    return n * factorial(n-1)
print(factorial1(5))

120
120

高阶函数

函数的参数或返回值是函数的函数,一般函数的参数是另一个函数的地址,看下面代码很好理解

def handle(func, *param):
    return func(*param)

def my_sum(*param):
    sum = 0
    for i in param:
        sum += i
    return  sum
print(my_sum(1,2,3,4,5,6))

# 函数的参数还是一个函数
print(handle(my_sum,1,2,3,4,5,6))

21
21

可能用到的高级函数

  • map(func, iterator) 该函数会把可迭代对象中的数据一次传递给func函数处理,最后把处理的结果返回
def power(x):
    return x*x
result = map(power,[1,2,3,4,5,6])
print(result)
print(list(result))

[1, 4, 9, 16, 25, 36]

  • reduce(func,iterator)
    reduce函数累积操作。func函数必须接收两个参数。reduce会把func的运行结果做一个参数,然后从iterator中导入另一个参数,注意,第一次会func会直接从iterator中导入两个参数作为其参数
from functools import reduce
li = [1,2,3,4,5]
result = reduce(lambda x,y:x * y,li)
print(result)

120

filter(func,inteable)

根据func来过滤interable。将interable中的数据传入函数func中如果函数返回True,就保留;否则过滤掉

li = [1,2,4,5,6,9,10,15]
result = list(filter(lambda x: x % 2 == 1,li))
print(result)

[1, 5, 9, 15]

  • .doc
    可以查看函数的文档随便举两个例子就知道他的用法了
from functools import reduce
print(reduce.__doc__)
print(map.__doc__)

reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
map(func, *iterables) --> map object
Make an iterator that computes the function using arguments from
each of the iterables. Stops when the shortest iterable is exhausted.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容

  • 1.函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。 函数能提高应用的模块性,和代码的重复...
    华丽的微笑阅读 677评论 0 1
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,819评论 0 38
  • 函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 上面代码检查函数l...
    呼呼哥阅读 3,392评论 0 1
  • 1.函数参数的默认值 (1).基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。
    赵然228阅读 693评论 0 0
  • 函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 上面代码检查函数l...
    陈老板_阅读 449评论 0 1