2019-08-02-函数

函数

review

1.概念: 对实现特定功能的代码的封装
2.函数的声明
def 函数名(形参列表):
函数说明文档
函数体
3.函数的调用
声明函数的时候不会执行函数体,调用函数才会执行函数体;一个函数调用多少次,函数体就会执行多少次

函数(实参列表) - 函数调用表达式

4.函数的调用过程(非常重要!):

  1. 回到函数声明的位置
  2. 传参(用实参给形参, 保证每个形参都有值)
  3. 执行函数体
  4. 执行完函数体,确定返回值
    a. 执行完函数体: 函数体对应的语句执行完; 执行函数体的时候遇到return
    b. 确定返回值: 看函数执行结束的时候有没有遇到return, 如果遇到return后面的值就是返回值;没有遇到就是None
  5. 回到函数调用的位置(这个时候函数调用表达式的值才是函数的返回值)

5.函数的参数
位置参数和关键字参数
参数默认值
参数类型说明
不定长参数

6.返回值

形参列表: 参数名1,参数名2,...
实参列表: 值1, 值2, 值3,...

def func1(x, y):
    # x=10, y=20
    print(x, y)
    return x+y   # return 30


print(func1(10, 20))

nums = [23, 89, 90, 76]
nums.sort(reverse=True)


def func3(x: int, names: list, gender='男') -> list:
    print(x, names, gender)
    return [1, 2, 3]


re = func3(1, ['nam'])
re.sort()

homework

3.编写一个函数,实现摇骰子的功能,打印N个骰子的点数和

def dice_sum(n: int):
    """
    求N个随机数的和(每个随机数是1-6)...
    :param n: 随机数的个数
    :return: 所有随机数的和
    """
    sum1 = 0
    for _ in range(n):
        num = random.randint(1, 6)
        print(num)
        sum1 += num
    return sum1


print('点数和:', dice_sum(3))

4.编写一个函数,交换指定字典的key和value。
例如: dict1 = {'a': 1, 'b': 2, 'c': 3} --> dict1 = {1: 'a', 2: 'b', 3: 'c'}

def change_key_value(dic: dict):
    for key in dic.copy():
        # 将取出来的value作为键, key作为值添加到字典中。并且删除原来的键值对
        dic[dic.pop(key)] = key

# {'a': 1, 'b': 2, 'c': 3}, {'b': 2, 'c': 3, 1:'a'}
# {'c': 3, 1: 'a', 2:'b'}


dict1 = {'a': 1, 'b': 2, 'c': 3}
change_key_value(dict1)
print(dict1)

8.写一个自己的capitalize函数,能够将指定字符串的首字母变成大写字母
例如: 'abc' -> 'Abc' '12asd' --> '12asd'

def capitalize(str1: str):
    char0 = str1[0]
    if 'a' <= char0 <= 'z':
        new_char0 = chr(ord(char0) - 32)
        return new_char0 + str1[1:]

    return str1


print(capitalize('k12asd'))

9.写一个自己的endswith函数,判断一个字符串是否以指定的字符串结束

def endswith(str1: str, str2: str):
    temp = str1[-len(str2):]
    if temp == str2:
        return True
    return False


print(endswith('abc123', '12z'))

12.写一个自己的rjust函数,创建一个字符串的长度是指定长度,原字符串在新字符串中右对齐,剩下的部分用指定的字符填充

def rjust(str1: str, width: int, char: str):
    return (width - len(str1)) * char + str1


print(rjust('abc', 5, '+'))

13.写一个自己的index函数,统计指定列表中指定元素的所有下标,如果列表中没有指定元素返回 - 1

def index(list1: list, obj):
    indexs = []
    for x in range(len(list1)):
        if list1[x] == obj:
            indexs.append(x)

    if indexs:
        return indexs
    return -1

17.写一个自己的replace函数,将指定字符串中指定的旧字符串转换成指定的新字符串
例如: 原字符串: 'how are you? and you?'
旧字符串: 'you'
新字符串: 'me'
结果: 'how are me? and me?'
方法一:

def replace1(str1: str, old: str, new: str):
    str_list = str1.split(old)
    return new.join(str_list)


print(replace1('how are you? and you?you', 'you', 'me'))

方法二:

def replace2(str1: str, old: str, new: str):
    x = 0
    old_length = len(old)
    new_str = ''
    while x < len(str1):
        temp = str1[x: x+old_length]
        if temp != old:
            new_str += str1[x]
            x += 1
        else:
            new_str += new
            x += old_length
    return new_str


print(replace2('how are you? and you?you', 'you', 'me'))

匿名函数

1.匿名函数

匿名函数就是没有函数名的函数; 匿名函数可以看成是类型是function的值和10, 'abc'是同类东西
注意: 匿名函数本质还是函数,函数中除了声明语法以外其他的都使用匿名函数

1)语法
lambda 参数列表: 返回值

2)说明
lambda - 关键字
函数名 = 参数列表 - 参数名1,参数名2,...
: - 固定
返回值 - 任何有结果的表达式;它是匿名函数的函数体,相当于普通函数中的return语句

调用匿名函数: 保存匿名函数值的变量(实参列表)

3)参数
普通函数中除了用'参数名:类型'的形式来指定参数类型以外,其他的语法匿名函数都支持

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

fn1 = lambda x, y: x+y
def fn1(x, y):
    # x=10, y = 30
    return x+y
"""
fn2 = lambda x: print('====')
"""
def fn2(x):
    return print('=====')
"""

print(fn1(10, 30))
print(fn2(10))

100   # int类型的数据
'abc'  # str类型的数据
[1, 2, 3]   # list类型的数据
{'a': 10, 'b': 20}    # dict类型的数据
lambda x: x   # function类型的数据

a = 100
str1 = 'abc'
list1 = [1, 2, 3]
dict1 = {'a': 10, 'b': 20}
fn1 = lambda x: x
print(a + 10, str1.replace('a', 'A'), list1[0], fn1(90))

list2 = [100, 'abc', [1, 2, 3], lambda x: x*2]
print(list2)
print(list2[0] * 10)
print(list2[1][0])
print(list2[-1](12))


sum1 = lambda x, y, z=3: x+y+z
sum3 = lambda *nums: sum(nums)

def sum2(x, y, z=0):
    return x+y+z

print(sum2(10 , 30), sum2(y=20, x=10))
print(sum1(1, 2), sum1(y=2, x=1))
print(sum3(1, 2, 3, 4, 5))

变量的作用域

1.变量的作用域: 变量在程序中能够使用的范围

2.全局变量和局部变量

1)全局变量: 没有声明在函数里面或者类里面的变量就是全局变量;
作用域是从声明开始到文件结束的任何位置
2)局部变量: 声明函数中的变量就是局部变量(函数的参数相当于声明在函数中的变量)
作用域是从声明开始到函数结束的任何位置

3)函数调用过程(内存): 压栈
当调用函数的时候, 系统会自动在内存的栈区间为这个函数开辟一个独立的内存区域,
用来保存在函数中声明的变量。当函数调用结束这个内存区域会自动释放。
print('==============全局变量================')
a = 10 # 全局变量

x是全局变量

for x in range(5):
    if False:
        c = 100
    b = 20   # 全局变量
    print('循环里面:', a)
    print('循环里面:', x)

print('外面:', b)

def func1():
    print('函数里面:', a)
    print('函数里面:', x)
    print('函数里面:', b)


func1()

print('===================局部变量===================')


def func2(x1=10, y1=20):
    z1 = 100
    print('函数内部:', x1, y1, z1)


func2()


# print('函数外部:', x1)   # NameError: name 'x1' is not defined
# print('函数外部:', z1)   # NameError: name 'z1' is not defined

3. global和nonlocal

global和nonlocal函数中的关键字,和return一样只能在函数体中使用
1)global - 在函数中声明一个全局变量
global 变量
变量 = 值

2)nonlocal: 在局部的局部中去修改局部变量的值
nonlocal 变量
变量 = 值

print('=============global=============')
a1 = 111
b1 = 100

def func3():
    # 这儿是在声明一个局部变量a1
    a1 = 222
    print('函数里面a:', a1)

    # 这儿的b1是全局变量
    global b1
    b1 = 333
    print('函数里面b:', b1)


func3()

print('函数外面a:', a1)
print('函数外面b:', b1)

print('================nonlocal=============')


def func4():
    a2 = 100

    def func5():
        nonlocal a2
        a2 = 500
        print('函数里面的函数里面a2:', a2)

    func5()

    print('函数里面a2:', a2)


func4()
# print(a2)    # NameError: name 'a2' is not defined



def func(str):
    # str = 'abc'
    sum = 0

func('hello world!')

print(str(100))

递归函数

1.什么是递归函数

自己调自己的函数(函数体中调用当前函数)
循环能做的事情,递归都可以做

注意: 能用循环解决的问题就不要用递归

# def func1():
#     print('=====')
#     func1()
#
#
# func1()

2.怎么写递归函数

第一步: 找临界值(循环结束的条件) - 在这儿需要结束函数
第二步: 找关系 - 找f(n)和f(n-1)的关系(找当次循环和上次循环的关系)
第三步: 假设函数的功能已经实现,根据关系用f(n-1)去实现f(n)的功能

用递归函数实现: 1+2+3+...+n

def sum1(n):
    # 第一步: 找临界值
    if n == 1:
        return 1
    # 第二步: sum1(n)和sum1(n-1)
    # sum1(n) == 1+2+3+...+n-1+n
    # sum1(n-1) == 1+2+3+ ... + n-1
    # sum1(n) = sum1(n-1) + n
    return sum1(n-1)+n


print(sum1(100))

用递归函数求斐波那契数列中第n个数: 1, 1, 2, 3, 5, 8, 13, 21,...

def sequence(n):
    if n == 1 or n == 2:
        return 1
    # 找关系:sequence(n)和sequence(n-1)
    # sequence(n) = sequence(n-1) + sequence(n-2)
    return sequence(n-1) + sequence(n-2)


print(sequence(1), sequence(2))
print(sequence(8))

练习: 用递归实现以下功能
n = 5




**

n=4



**

"""

def print_star(n):
    if n == 1:
        print('*')
        return
    # 找关系: 打印n个*, 再实现f(n-1)的功能
    print(n * '*')
    print_star(n-1)


print_star(3)

练习: 用递归实现以下功能
n=3

**


n=4

**



迭代器

1.迭代器(iter)

迭代器作为容器可以保存多个数据;数据的来源: 1)将其他序列转换成迭代器 2)生成器
1)将其他序列转换成迭代器

iter1 = iter('abc')
print(iter1, type(iter1))

iter2 = iter([12, 30, 90])
print(type(iter2))

2.获取元素

不管用那种方式去获取了元素的值,那么这个元素在迭代器中就不存在了
1)获取单个元素:next(迭代器)、迭代器.next() -> 获取迭代器中的第一个元素
2)遍历:
for 变量 in 迭代器:
pass

iter3 = iter('hello')
print(next(iter3))
print(next(iter3))
print(next(iter3))
print(iter3.__next__())

# for x in range(100):
#     print(x)

print(next(iter3))
# print(next(iter3))   # StopIteration  如果迭代器为空,用next获取元素的时候会报错

iter4 = iter('world')
for x in iter4:
    print(x)

# print(next(iter4))    # StopIteration

print('===============')
iter4 = iter('world')
print(next(iter4))

for x in iter4:
    print('循环:', x)

生成器

import time

1.什么是生成器

1)生成器就是迭代器中的一种

  1. 调用一个带有yield关键字的函数就可以得到一个生成器
    如果一个函数中有yield关键字:
    a. 调用函数不会执行函数体
    b. 函数调用表达式的值不是函数的返回值,而是一个生成器对象

1.怎么去创建一个生成器

def func1():
    print('=======')
    if False:
        yield
    return 100


gen1 = func1()    # 这儿的gen1就是一个生成器对象
print('外部:', gen1)

2.生成器产生数据的原理

  1. 一个生成器能够产生多少数据,就看执行完生成器对应的函数的函数体会遇到几次yield;
    yield后面的值就是生成器能够产生的数据

2)每次获取生成器中的元素的时候,都是先去执行函数体,直到遇到yield,并且将yield后面的值作为获取元素的结果;
并且保留结束的位置,下次获取下一个值的时候,从上次结束的位置接着执行函数体,直到遇到yield...
如果从开始执行到函数结束都没有遇到yield,就会报StopIteration错误
print('================2==========')

def func2():
    print('+++++')
    yield 1
    print('-----')
    yield 100     # yield 后边可以跟数据;同一个函数可以有多个yield


gen2 = func2()
print(gen2)

print('函数外部:', next(gen2))
print('函数外部:', next(gen2))
# print('函数外部:', next(gen2))   # StopIteration


def func3():
    print('第一段代码')
    yield
    print('第二段代码')
    yield
    print('第三段代码')
    yield


gen3 = func3()

time.sleep(1)
next(gen3)
time.sleep(1)
next(gen3)
time.sleep(1)
next(gen3)

练习:

def func4():
    # x = 0
    for x in range(0, 100, 3):
        yield x


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

推荐阅读更多精彩内容

  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,763评论 0 38
  • 函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 上面代码检查函数l...
    呼呼哥阅读 3,363评论 0 1
  • 函数参数的默认值 基本用法 在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。 上面代码检查函数l...
    陈老板_阅读 447评论 0 1
  • 百日练,一百天看一百本书,第25天,《你所谓的稳定,不过是在浪费生命》看到355页,理解70%,2500字/分钟。...
    骑了蜗牛闯世界阅读 219评论 0 0
  • 本文参加#感悟三下乡,青春筑梦行#活动,本人承诺,文章内容为原创,且未在其他平台发表过。 三下乡...
    小Demon阅读 647评论 0 2