函数(function)

# -*- coding: utf-8 -*-
# @Time    : 2019/11/8 8:55
# @Author  : John
# @Email   : 2398344557@qq.com
# @File    : 函数.py
# @Software: PyCharm
  • 函数的格式:
# def 函数名():
#     函数实现
#     pass    # pass空语句
  • 定义一个函数
def say_hello():
    print('hello, xuebi')
# 调用
say_hello()
# —— hello, xuebi
  • 函数执行的顺序:调用时候才会执行
# # 栗子:
num = 100
print(num)
def say_hello():
    print('hello1')
    print('hello2')
    print('hello3')
print('xuebi')
# 调用
say_hello()
print('1233')
# 运行顺序:num = 10
#          print(num)
#          print('xuebi')
#          say_hello()
#          print('hello1')
#          print('hello2')
#          print('hello3')
#          print('1233')
—— 100
   xuebi
   hello1
   hello2
   hello3
   1233
  • 用函数的原因
# 为啥要用函数:
# 栗子:
str1 = 'abcdefg'
str1 = str1[:2] + 'z' + str1[3:]
print(str1)
# —— abzdefg
str2 = '1234567'
str2 = str2[:2] + '8' + str2[3:]
print(str2)
# —— 1284567

# 找规律改进,封装成函数:
def set_str(msg, index, char):
    # 函数文档字符串
    """
    将目标字符串的指定位置进行替换
    :param msg:     目标字符串
    :param index:     替换字符串的索引位置
    :param char:     要替换的字符
    :return:     返回替换完成的字符串
    """
    # 对给定的char进行判断:isinstance(char, type),判断两个变量是否属于某种类型
    if isinstance(char, int):
        char = str(char)
    return msg[:index] + char + msg[index+1:]
res1 = set_str('1234567', 2, 9)
res2 = set_str('abcdefg', 2, 'o')
print(res1)
print(res2)
# —— 1294567
# abodefg
  • 函数的形参和实参

形参:形式参数
实参:实际调动的参数
区别:

  1. 形参是虚拟的,不占内存空间,形参变量只有在被调用的时候才分配内存空间
  2. 实参是一个变量,占用内存空间

注意:数据是单向传送的,实参传给形参

【实例1】求一个矩形的面积

def area(width, length):
    return width*length
print(area(width=4, length=6))    # 实参,指定返回值,位置可变
print(area(length=6, width=4))    # 实参,指定返回值,位置可变
print(area(4, 6))    # 位置不能换,指顺序传给函数
—— 24
   24
   24
  • 函数参数
# 1. 必须参数:以正确的顺序传入参数,调用时必须和声明的时候保持一致,不然会报错

# def f():
#     pass
# f('xuebi')
# # —— TypeError: f() takes 0 positional arguments but 1 was given
# ------------
# def f(name, age):
#     print('我叫%s'%(name), '我今年%d岁了'%(name, age))
# f('xuebi')
# # —— TypeError: f() missing 1 required positional argument: 'age'
# ------------
def f(name, age):
    print('我叫%s,我今年%d岁了'%(name, age))
f('xuebi', 18)
# —— 我叫xuebi,我今年18岁了
# ------------
def f(name, age):
    print('我叫%s,我今年%d岁了'%(name, age))
f(19, 'xuebi')
# —— TypeError: %d format: a number is required, not str
# 解决方法:===>


# 2. 关键字参数,允许函数调用时参数的顺序可以与声明不一致,因为python解释器能够用参数名匹配参数值
def f(name, age):
    print('我叫%s,我今年%d岁了'%(name, age))
f(age=18, name='xuebi')
# —— 我叫xuebi,我今年18岁了


# 3. 默认参数(缺省参数)
# 在调用函数是,缺省的参数如果没有被传入,则会使用默认值
def f(name, age, sex='male'):
    print('我叫%s,我今年%d岁了'%(name, age))
    print('性别%s'%(sex))
f(age=18, name='xuebi')    # 没有传入相应sex参数时,返回sex的默认值male
# —— 我叫xuebi,我今年18岁了
# 性别male
f(age=18, name='xuebi', sex='female')    # 有相应的sex参数传入时会对默认值进行修改或覆盖,相同时忽略
# —— 我叫xuebi,我今年18岁了
# 性别female


# 4. 不定长参数
# 一个函数能处理比当初声明时更多的参数
# def funcname(*args, **kwargs):
#     """文档字符串"""
#     pass
# 或
# def funcname([formal_args,...]*args, **kwargs):
#     """文档字符串"""
#     pass

# 加了星号(*)的变量args(此命名不唯一),会存放所有未命名的变量参数,args为元组
# 加了星星号(**)的变量kwargs(此命名不唯一),会存放命名参数,即形如key=value的参数,kewargs为字典
def func(a, b, *args, **kwargs):
    """
    可变参数演示范例
    :param a: formal_args
    :param b: formal_args
    :param args: 未命名的变量参数args为元组
    :param kwargs: 命名参数kwargs为字典
    :return: 无
    """
    print('a=', a)
    print('b=', b)
    print('args=', args)
    print('kwargs=')
    for k, v in kwargs.items():
        print(k, '---->', v)

# 情况一:
func(1, 2, 3, 4, 5, m=6, n=7, p=8)
# —— a= 1
# b= 2
# args= (3, 4, 5)
# kwargs=
# m ----> 6
# n ----> 7
# p ----> 8

# 情况二:
c = (3, 4, 5)
d = {'m': 6, 'n': 7, 'p': 8}
func(1, 2, *c, **d)
# —— a= 1
# b= 2
# args= (3, 4, 5)
# kwargs=
# m ----> 6
# n ----> 7
# p ----> 8

# 情况三:
c = (3, 4, 5)
d = {'m': 6, 'n': 7, 'p': 8}
func(1, 2, c, d)
# —— a= 1
# b= 2
# args= ((3, 4, 5), {'m': 6, 'n': 7, 'p': 8})
# kwargs=
  • 函数的返回值
    如果想要获取函数的执行结果,我们一般要设置编写函数的返回值,使用return可以把结果返回

return 的作用:

  1. 停止这个函数的执行,返回指定的结果
  2. Python中的return可以返回多个结果(对象),解释器会将其组装成一个元组作为一个整体结果输出
  3. 如果未指定return,那么这个函数的返回值是None值

【实例2】给定一个列表,将列表中所有数字进行累加,并且返回他们的累加和以及平均数

def sum_and_average(list):
    """

    :param list: 给定一个列表
    :return: 返回他们的累加和以及平均数
    """
    sum = 0
    count = 0
    average = 0
    for x in list:
        if isinstance(x, int) or isinstance(x, float):
            # 进行累加
            sum += x
            # 计数
            count += 1
    average = sum/count
    return sum, average
li = [20, 15, 2.8, 'a', 35, 5.9, -1.8]
print(sum_and_average(li))    # 输出的是一个元组
# —— (76.9, 12.816666666666668)
print('累计和:', sum_and_average(li)[0])    # 输出元组第一个元素
# —— 累计和: 76.9
print('平均数:', sum_and_average(li)[1])    # 输出元组第二个元素
# —— 平均数: 12.816666666666668
  • 匿名函数(lambda表达式)
  1. 不需要显示指定名字的函数
  2. lambda 的参数可以是无限个,但返回的表达式只能有一个
  3. 主要目的:联合其他函数使用

格式:函数名 = lambda 参数1, 参数2, ... 参数n : 返回表达式

优点:

  1. 不用担心函数名冲突,
  2. 减少代码量,
  3. 优雅

【练习1】两数相乘

def mul(x, y):
    return x*y
# 或用lambda:
mul2 = lambda x, y: x*y
print(mul2(3, 4))
# —— 12

【练习2】将x和y进行比较,如果x>y,返回x*y;否则返回x/y

def cheng_chu(x, y):
    """
    两个数对比之后进行计算
    :param x: 传入的第一个参数
    :param y: 传入的第二个参数
    :return: 当x>y时返回x*y;当x<y时返回x/y
    """
    if x > y:
        return x*y
    else:
        return x/y
print(cheng_chu(2, 5))
# —— 0.4
print(cheng_chu(5, 2))
# —— 10
# 或用lambda+三目运算符:
cheng_chu2 = lambda x, y: (x*y if x > y else x/y)
print(cheng_chu2(10, 25))
# —— 0.4

【插曲】回顾:三目运算符

store = ['']
if len(store) == 0:
    store = '当当自营'
else:
    store = store[0]
# 或用三目表达式:
print('当当自营' if len(store) == 0 else store[0])

函数作用域

x = 100
x = str(100)   # 强制类型转换
print('hello' + x)
# —— hello100

str = 90    # built-in作用域(python自带的函数或已经定义好的)。改变类型为数据,不再是内置函数
y = str(100)
print('hello' + x)
# —— TypeError: 'int' object is not callable
# # 结论:定义的变量不要与保留字和函数重叠
g_counter = 33    # 全局作用域

def outer():
    o_count = 0    # 嵌套作用域(函数范围内可用)

    def inner():
        i_counter = 10    # 局部作用域(离开局部作用域之后,数据销毁)
        print(i_counter)
        print(o_count)
        print(g_counter)
    inner()
    # print(i_counter)
    print(o_count)
    print(g_counter)
outer()
# print(i_counter)
# print(o_count)
print(g_counter)

# # 结论:作用域遵循就近原则(LEGB)
# L:
# E:
# G:
# B:
10
0
33
0
33
33
x = 90
def f2():
    global x
    x += 88
print(x)
f2()
print(x)    # 此时全局变量x已经发生变化
—— 90
   78
a = 666

def outer():
    out_count = 3
    def inner():
        # global out_count    # 在全局作用域找
        nonlocal out_count    # 非本地非全局作用域(嵌套作用域)
        out_count += 3

    inner()
    print(out_count)

outer()
—— 6

递归函数

【练习】阶乘

def jiecheng(n):
    ret = n
    for i in range(1, n):
        ret *= i
    return ret
result = jiecheng(5)
print(result)
—— 120

【练习】求n的阶乘

def jiecheng_new(n):
    if n == 1:    # 终止步骤
        return 1
    return n * jiecheng_new(n-1)
result = jiecheng_new(6)
print(result)
—— 720

【练习】斐波那数列

def fibo(n):
    before = 0
    after = 1

    for i in range(n-1):     # 循环次数等于输入的位置-1
        ret = before + after    # 指针往后挪一位
        before = after    # 指针往后挪一位
        after = ret
        print(before, end='\t')

    return ret
print(fibo(9))
—— 1    1   2   3   5   8   13  21  34

【练习】斐波那契数列

def fibo(n):
    if n <= 1:    # 终止条件
        return n
    return fibo(n-1)+fibo(n-2)
print(fibo(7))
—— 13
# 缺点:效率不高且无法打印执行过程

【练习】斐波那数列(缓存,可提高运行速度)

cache = {}
def fibo(n):
    if n <= 1:    # 终止条件
        return n

    if (n-1) not in cache:
        cache[n-1] = fibo(n-1)
    if (n-2) not in cache:
        cache[n-2] = fibo(n-2)
    return cache[n-1] + cache[n-2]
print(fibo(100))
—— 354224848179261915075

【练习】水仙花

# 要求:153 = 1立方 + 5立方 + 3立方
n = int(input('请输入数字:'))
a = n % 10
b = (n % 100-a)//10
c = (n % 1000-(b*10)-a)//100
if (a**3 + b**3 + c**3) == n:
    print('{}是个水仙花数'.format(n))
else:
    print('{}不是水仙花数'.format(n))
—— 请输入数字:153
   153是个水仙花数
   请输入数字:100
   100不是水仙花数

【自己版】

def flower():
    flowers = []
    for n in range(100, 10000):
        a = n % 10
        b = (n % 100 - a) // 10
        c = (n % 1000 - (b * 10) - a) // 100
        if (a ** 3 + b ** 3 + c ** 3) == n:
            # print('{}是个水仙花数'.format(n))
            flowers.append(n)
    print(flowers)
flower()
—— [153, 370, 371, 407]

【老师版】

flowers = []
def flower():
    for i in range(100, 1000):
        gewei = i % 10
        shiwei = (i // 10) % 10    # 取百位跟十位,然后再取余拿十位数
        baiwei = i // 100
        if gewei*gewei*gewei + shiwei*shiwei*shiwei + baiwei*baiwei*baiwei == i:
            flowers.append(i)
flower()
print(flowers)
—— [153, 370, 371, 407]

【拓展版】

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

推荐阅读更多精彩内容