Python学习笔记

文章目录

  • Python学习笔记
  • 第十站 水晶球不调用不动
    • 1. 函数的创建和调用
    • 2. 函数的参数传递
    • 3. 函数的返回值
    • 4. 函数的参数定义
    • 5. 变量的作用域
    • 6. 递归函数
    • 7. 本章作业

课程笔记参考B站视频: Python全栈开发教程。


第十站 水晶球不调用不动

这个水晶球就是“函数”。

1. 函数的创建和调用

函数就是执行特定任和以完成特定功能的一段代码。函数的优点包括:复用代码、隐藏实现细节、提高可维护性、提高可读性便于调试等。函数的创建和调用格式如下:

'''函数的创建格式'''
def 函数名([形式参数]):函数体[return xxx]'''函数的调用格式'''
函数名([实际参数])

注:要先定义函数,才能进行调用

下面是代码示例:

def cal(a,b):c=a+breturn cresult = cal(10, 20)
print(result)
  • 运行结果
30

2. 函数的参数传递

函数调用的参数传递主要有两种方式:

  1. 按照位置传递实参:根据 形参对应的位置 进行实参传递,顺序不可改变。
  2. 按照关键字传递实参:根据 形参名称 进行实参传递,顺序可以改变。

下面是代码示例:

def cal(a,b):c=a+breturn cprint('位置传递:', cal(10, 20))
print('关键字传递:', cal(b=20,a=100)) # 左侧的变量名称称为关键字参数
  • 运行结果
30
120

下面以一个程序来举例,说明函数调用时参数传递的内存分析图。

def fun(arg1, arg2):print('arg1=', id(arg1), arg1)print('arg2=', id(arg2), arg2)arg1 = 100arg2.append(10)print('arg1=', id(arg1), arg1)print('arg2=', id(arg2), arg2)# returnn1 = 11
n2 = [22, 33, 44]
print('调用函数前:', id(n1), n1)
print('调用函数前:', id(n2), n2)
print('---调用函数中----')
fun(n1, n2)
print('----------------')
print('调用函数后:', id(n1), n1)
print('调用函数后:', id(n2), n2)

上面这个程序在运行的过程中,其内存分析图如下:

最终其运行结果为:

调用函数前: 140718152341472 11
调用函数前: 2535859027008 [22, 33, 44]
---调用函数中----
arg1= 140718152341472 11
arg2= 2535859027008 [22, 33, 44]
arg1= 140718152344320 100
arg2= 2535859027008 [22, 33, 44, 10]
----------------
调用函数后: 140718152341472 11
调用函数后: 2535859027008 [22, 33, 44, 10]

即,在函数调用过程中,进行参数的传递:

  1. 如果是不可变对象,在函数体的修改不会影响实参的值。
  2. 如果是可变对象,在函数体的修改会影响实参的值。

3. 函数的返回值

函数的返回值有如下情况:

  1. 若函数没有返回值,return可以省略不写。
  2. 若函数的返回值只有1个,直接返回其类型。
  3. 若函数的返回值有多个,返回的结果为元组。

下面是代码示例:

def fun(num):odd = [] # 定义空列表even = []for i in num:if i%2:odd.append(i)else:even.append(i)return odd, evenresult = fun(range(-1,-10,-1))
print(result)
print('奇数列表为:', result[0])
print('偶数列表为:', result[1])
  • 运行结果
([-1, -3, -5, -7, -9], [-2, -4, -6, -8])
奇数列表为: [-1, -3, -5, -7, -9]
偶数列表为: [-2, -4, -6, -8]

4. 函数的参数定义

函数的参数定义除了可以直接声明变量,还有三种特殊方式:

  1. 默认值参数:函数定义时给形参设置默认值,只有与默认值不符的时候才需要传递实参。
  2. 个数可变的位置参数:适用于无法确定要传递的位置实参的个数时,使用*定义,类型为元组
  3. 个数可变的关键字参数:适用于无法确定要传递的关键字实参的个数时,使用**进行定义,类型为字典

注:对于第二种和第三种参数,只能定义一个。
注:若同时都有定义,第二种必须放在第三种之前(两个星号的必须在前面)。

下面是代码示例:

def fun1(a, b=10):  # 默认值参数print(a, b)returndef fun2(*args):    # 可变的位置参数print(args)def fun3(**args):   # 可变的位置参数print(args)def fun4(*args1, **args2):      # 不会报错pass
# def fun5(**args1, *args2):   # 会报错,SyntaxError: invalid syntax
#     passprint('---------默认值参数---------')
print('传递1个参数:', fun1(100))
print('传递2个参数:', fun1(100, 20))
print('-----个数可变的位置参数------')
fun2(10)
fun2(10, 20)
fun2(10, 20, 30)
print('-----个数可变的关键字参数-----')
fun3(a=10)
fun3(a=10, b=20)
fun3(a=10, b=20, c=30)
  • 运行结果
---------默认值参数---------
100 10
传递1个参数: None
100 20
传递2个参数: None
-----个数可变的位置参数------
(10,)
(10, 20)
(10, 20, 30)
-----个数可变的关键字参数-----
{'a': 10}
{'a': 10, 'b': 20}
{'a': 10, 'b': 20, 'c': 30}

同时从上面的代码结果中可以看出,一条语句包含函数时,会首先运行函数体,再运行该条语句。

最后总结一下函数的参数类型:

分类 参数的类型 备注
函数的调用 位置实参
将元组、列表、集合的每个元素都转换成位置实参 使用*
关键字实参
将字典的所有键值对都转换成关键字实参 使用**
函数的定义 默认值形参
关键字形参 使用*
个数可变的位置形参 使用*
个数可变的关键字形参 使用**

下面是函数的调用代码示例:

def fun(a, b, c):print('a =', a, ' b =', b, ' c =', c)print('-----函数调用实参的不同方式------')
print('位置实参:', end='')
fun(10, 20, 30)         # 位置实参
print('元组、列表、集合转换成位置实参:', end='')
lst = {40, 50, 60}      # 元组、列表、集合都可以
fun(*lst)               # 调用时将每个元素都转换成 位置实参
print('关键字实参:', end='')
fun(a=70, b=80, c=90)   # 关键字实参
print('字典转换成关键字实参:', end='')
dic = {'a':100, 'b':110, 'c':130}
fun(**dic)              # 调用时将所有键值对都转换成 关键字实参
  • 运行结果
-----函数调用实参的不同方式------
位置实参:a = 10  b = 20  c = 30
元组、列表、集合转换成位置实参:a = 40  b = 50  c = 60
关键字实参:a = 70  b = 80  c = 90
字典转换成关键字实参:a = 100  b = 110  c = 130

下面是函数的定义代码示例:

def fun1(a, b=10):  # a为位置形参,b为默认值形参print('a =', a, ' b =', b)def fun2(*args):    # 个数可变的位置形参print(args)def fun3(**args):   # 个数可变的关键字形参print(args)def fun4(a,b,c):print('a =', a, ' b =', b, ' c =', c)def fun5(a,*,b,c):  # 星号后面都必须使用关键字实参print('a =', a, ' b =', b, ' c =', c)print('-------演示fun1()---------')
print('-------演示fun2()---------')
fun2(10, 20, 30)
print('-------演示fun3()---------')
fun3(a=10, b=20)
print('-------演示fun4()---------')
fun4(10, 20, 30)        # 位置实参
fun4(a=40, b=50, c=60)  # 关键字实参
fun4(40, 50, c=60)      # 前两个位置实参,后一个关键字实参
print('-------演示fun5()---------')
# fun5(40, 50, c=60)   # 会报错说少一个关键字实参
fun5(40, c=50, b=60)
  • 运行结果
-------演示fun1()---------
-------演示fun2()---------
(10, 20, 30)
-------演示fun3()---------
{'a': 10, 'b': 20}
-------演示fun4()---------
a = 10  b = 20  c = 30
a = 40  b = 50  c = 60
a = 40  b = 50  c = 60
-------演示fun5()---------
a = 40  b = 60  c = 50

函数定义参数时的顺序(从前到后):位置形参 > 关键字形参、可变数量位置形参 > 可变数量关键字形参。若有一个单独的星号(表明其后面都是关键字形参),则可变数量位置形参一定要提前到该星号之前。

5. 变量的作用域

变量的作用域指的是程序代码能访问该变量的区域,在作用域之外调用变量会报错。根据变量的有效范围可分为:

  1. 局部变量:在函数内定义并使用的变量,只在函数内部有效,局部变量使用global声明,这个变量
    就会就成全局变量。
  2. 全局变量:函数体外定义的变量,可作用于函数内外。

在下面这段代码中,c称为局部变量,变量a, b作为函数的形参,作用范围也是函数内部,也就是局部变量。于是在函数体外部调用a, b, c就会报错。

def fun(a, b):c = a+b  # c称为局部变量print(c)# print(a) # 会报错

在下面这段代码中,name是全局变量,在函数体内部和外部都可以使用,所以会打印两次。(C/C++不是这样的!!)

def fun2():print(name)name = '张三'
print(name)
fun2()
  • 运行结果
张三
张三

下面这段代码中,age本来作为局部变量,只能作用于函数体内部,但其使用 global声明,就成为全局变量,在函数体外部也可以调用。

def fun3():global notenote = '去码头整点薯条'print(note)fun3()
print(note)
  • 运行结果
去码头整点薯条
去码头整点薯条

6. 递归函数

如果在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数。递归(递推、回归)由 递归调用 与 递归终止条件 两部分组成。进行递归时,每递归调用一次函数,都会在栈内存分配一个栈帧,当执行完本次函数,就会释放相应的空间只返回结果,如此循环直到完成整个递归。递归的优缺点如下:

缺点:占用内存多,效率低下。
优点:思路和代码简单。

下面是代码示例:

'''递归计算阶乘'''
def fac(n):if(n==1):return 1else:res = n*fac(n-1)return resprint('4的阶乘为:', fac(4))
  • 运行结果
4的阶乘为: 24

在调用递归函数的语句打上断点,进入调试模式,然后一直执行步入(step into),便可以在调试(debugger)窗口看到函数fac递推到回归的整个过程。

课堂作业:使用递归完成斐波那契数列的计算。
下面是代码示例:

'''
斐波那契数列:前两项均为1,此后的每一位都是前两项的和。
'''
'''下面这个函数体没有用到递归但是算出来了'''
'''函数体功能:输入序列长度,返回相应长度的斐波那契数列。'''
def fibo_sequ(mindex):sequ=[1]index = 1while index<mindex:if (index == 1):sequ.append(1)else:sequ.append(sequ[-1]+sequ[-2])index += 1return sequ
print(fibo_sequ(6))'''使用递归,但是只能计算单个元素的值'''
'''函数体功能:使用递归计算单个索引下的斐波那契数列值'''
def fib(n):if(n==1):return 1elif(n==2):return 1else:return fib(n-1)+fib(n-2)
for i in range(1,7,1):print(fib(i), end=' ')
  • 运行结果
[1, 1, 2, 3, 5, 8]
1 1 2 3 5 8

设置输出100个斐波那契数列的值,可以观察到使用递归的方法会非常的慢。并且从代码逻辑上说,显然使用递归会非常的浪费内存。

7. 本章作业

1. Mini计算器

说明:使用函数完成加、减、乘、除运算。

下面是代码示例:

def mini_cal(a, b, operation):if operation=='+':return a+belif operation=='-':return a-belif operation=='*':return a*belif operation=='/':if b!=0:return a/belse:return '除数不能为0'else:return '运算符输入错误'
if __name__ == '__main__':a = int(input('请输入第一个整数:'))b = int(input('请输入第一个整数:'))oper = input('请输入运算符:')print(mini_cal(a, b, oper))
  • 运行结果
请输入第一个整数:10
请输入第一个整数:0
请输入运算符:/
除数不能为0

2. 猜数游戏

说明:使用函数完成猜数游戏。

下面是代码示例:

import random
def guess(num_rand, num_guess):if num_rand>num_guess:return '猜小了'elif num_rand<num_guess:return '猜大了'elif num_rand==num_guess:return '猜对了'
if __name__=='__main__':num_rand = random.randint(0,100)for i in range(7,0,-1):num_guess = int(input('请输入一个0~100的整数:'))res = guess(num_rand,num_guess)if res!='猜对了' and i>1:print(res + f',你还有 {i-1} 次机会')elif res!='猜对了' and i==1:print(res + ',机会已经用完了~')else:print(res)break
  • 运行结果
请输入一个0~100的整数:50
猜大了,你还有 6 次机会
请输入一个0~100的整数:25
猜小了,你还有 5 次机会
请输入一个0~100的整数:37
猜大了,你还有 4 次机会
请输入一个0~100的整数:31
猜小了,你还有 3 次机会
请输入一个0~100的整数:34
猜对了

Python学习笔记:第十站 水晶球不调用不动相关推荐

  1. Python学习笔记第二十九天(N维数组(ndarray))

    Python学习笔记第二十九天 N维数组(ndarray) 构建阵列 索引阵列 ndarray的内部内存布局 阵列属性 内存布局 数据类型 其他属性 阵列接口 ctypes外部功能接口 Array方法 ...

  2. Python学习笔记(十九)面向对象 - 继承

    Python学习笔记(十九)面向对象 - 继承 一.继承的概念 # 继承:子类继承父类的所有方法和属性# 1. 子类 class A(object):def __init__(self):self.n ...

  3. Python学习笔记:第二站 七十二变

    Python学习笔记 文章目录 Python学习笔记 第二站 七十二变 1. 二进制与字符编码 2. Python中的标识符与保留字 3. Python中的变量 4.Python中的数据类型 5. P ...

  4. Python学习笔记:第九站 一串连一串

    Python学习笔记 文章目录 Python学习笔记 第九站 一串连一串 1. 字符串的驻留机制 2. 字符串的常用操作 3. 字符串的比较 4. 字符串的切片操作 5. 格式化字符串 6. 字符串的 ...

  5. 【Python学习笔记】b站@同济子豪兄 用pytorch搭建全连接神经网络,对Fashion-MNIST数据集中的时尚物品进行分类

    [Python学习笔记]原作b站@同济子豪兄 用pytorch搭建全连接神经网络,对Fashion-MNIST数据集中的时尚物品进行分类 跟着b站@同济子豪兄的视频自学写的代码,内容是用pytorch ...

  6. Python学习笔记(十五):类基础

    以Mark Lutz著的<Python学习手册>为教程,每天花1个小时左右时间学习,争取两周完成. --- 写在前面的话 2013-7-24 23:59 学习笔记 1,Python中的大多 ...

  7. Python学习笔记(十九)——Matplotlib入门

    目录 Matplotlib简介 导入matplotlib模块 图的参数说明 matplotlib图像组成部分介绍 matplotlib绘图步骤分析 matplotlib实现简单图像 matplotli ...

  8. Python学习笔记整理(十五)类的编写细节

    类代码编写细节 一.class语句 一般形式 class    <name>(superclass,...):     data=value     def mothod(self,... ...

  9. python学习笔记(十二)标准库os

    os 模块提供了访问操作系统服务的功能,它所包含的内容比较多. >>> import os >>> dir(os) ['EX_CANTCREAT', 'EX_CON ...

最新文章

  1. HttpSender OkHttp+RxJava超好用、功能超级强大的Http请求框架
  2. Windows Azure Platform Introduction (2) 云计算的分类和服务层次
  3. SDCC 2015架构专场札记:一线互联网公司的架构实践
  4. 对于redis底层框架的理解(一)
  5. python 获取向上两级路径_全国计算机二级Python真题解析-1
  6. bzoj 4319 cerc2008 Suffix reconstruction——贪心构造
  7. mysql数据库插入datetime_往MySQL数据库datetime类型字段中插入数据库的当前时间
  8. ASP.NET中 DataGrid简单自定义分页
  9. Oracle学习笔记:手工注册oracle的oledb驱动
  10. It seems that scikit-learn has not been built correctly.
  11. 中的draw函数_哪一个热图函数更快?
  12. 设计模式17---设计模式之模板方法模式(Template Method)(行为型)
  13. 几种经典病毒动力学模型【基于matlab的动力学模型学习笔记_3】
  14. 金蝶登录服务器不显示名称,金蝶云服务器如何登陆不了
  15. 微信支付 postman_小刘同学微信支付接入全笔记
  16. 解决安装ENVI5.3报错:the installation of MSVC_2010_SP1_x64_32bit has failed
  17. 别再眼红别人家的年终奖了,这才是大多数人的现状!
  18. 场景化AI数据推动智慧家居发展
  19. Excel 操作 插件 方方格子 工作簿未按字母顺序排列 重名工作簿名 并拆分成工作表
  20. SpringCloud和SpringCloudAlibaba的区别

热门文章

  1. vue的methods属性的方法中出现回调函数,在回调函数内部获取data中的数据
  2. 阿里国际站新出的优品抢位会是弯道超车的新机会吗?
  3. Java--通讯录管理系统【课程设计】
  4. 怎么将wav转换成mp3
  5. 飞桨带你使用度量学习,提升人脸识别准确率
  6. 全息干涉图补零尺寸与三种重构方法重建像间的关系研究
  7. 关于计算机与MCU通信及MAX232、CH340T与PL2303的区别
  8. Python安装Image库
  9. 2019年参加 PMP 认证考试了,通过的人心得分享
  10. 强势测试思维和弱势测试思维