2020-10-21 DAY6 函数用法_mysql2020-10-21怎么用date表示-程序员宅基地

技术标签: python学习  

目录

 

函数简介

函数的基本概念

Python 函数的分类

函数的定义和调用

变量的作用域(全局变量和局部变量)

参数的传递

浅拷贝和深拷贝

函数的参数的类型

lambda 表达式

eval()函数

递归函数

嵌套函数(内部函数)

nonlocal 关键字

LEGB 规则


函数简介

函数是可重用的程序代码块。函数的作用,不仅可以实现代码的复用,更能实现代码的 一致性。一致性指的是,只要修改函数的代码,则所有调用该函数的地方都能得到体现。

函数的基本概念

1. 一个程序由一个个任务组成;函数就是代表一个任务或者一个功能。

2. 函数是代码复用的通用机制。

Python 函数的分类

Python 中函数分为如下几类:

1. 内置函数 我们前面使用的 str()、list()、len()等这些都是内置函数,我们可以拿来直接使用。

2. 标准库函数 我们可以通过 import 语句导入库,然后使用其中定义的函数

3. 第三方库函数 Python 社区也提供了很多高质量的库。下载安装这些库后,也是通过 import 语句导 入,然后可以使用这些第三方库的函数

4. 用户自定义函数 用户自己定义的函数,显然也是开发中适应用户自身需求定义的函数。今天我们学习的 就是如何自定义函数。

函数的定义和调用

定义函数的语法如下:

def 函数名 ([参数列表]) :  

     '''文档字符串'''                               #我们调用 help(函数名.__doc__)可以打印输出函数的文档字符串

    函数体/若干语句

要点:

1. 我们使用 def 来定义函数,然后就是一个空格和函数名称;

    (1) Python 执行 def 时,会创建一个函数对象,并绑定到函数名变量上。

2. 参数列表

  (1) 圆括号内是形式参数列表,有多个参数则使用逗号隔开

  (2) 形式参数不需要声明类型,也不需要指定函数返回值类型

  (3) 无参数,也必须保留空的圆括号

  (4) 实参列表必须与形参列表一一对应

3. return 返回值

  (1) 如果函数体中包含 return 语句,则结束函数执行并返回值;

  (2) 如果函数体中不包含 return语句,则返回 None 值。

4. 调用函数之前,必须要先定义函数,即先调用 def 创建函数对象

  (1) 内置函数对象会自动创建

  (2) 标准库和第三方库函数,通过 import 导入模块时,会执行模块中的 def 语句

变量的作用域(全局变量和局部变量)

变量起作用的范围称为变量的作用域,不同作用域内同名变量之间互不影响。变量分为:全 局变量、局部变量。

全局变量:

1. 在函数和类定义之外声明的变量。作用域为定义的模块,从定义位置开始直到模块 结束。

2. 全局变量降低了函数的通用性和可读性,应尽量避免全局变量的使用。

3. 全局变量一般做常量使用。

4. 函数内要改变全局变量的值,使用 global 声明一下

测试操作:全局变量的作用域测试

a=100         #全局变量
def f1():
    global a  #在函数内部要使用全局变量a,必须先用global声明
    print(a)  #打印全局变量a
    a=300
f1()
print(a)

输出结果:
100
300

局部变量:

1. 在函数体中(包含形式参数)声明的变量。

2. 局部变量的引用比全局变量快,优先考虑使用。

3. 如果局部变量和全局变量同名,则在函数内隐藏全局变量,只使用同名的局部变量

测试操作:全局变量和局部变量同名

a=100     #全局变量
def f1():
    a = 3 #同名的局部变量
    print(a)
f1()
print(a)

运行结果:
3
100

参数的传递

函数的参数传递本质上就是:从实参到形参的赋值操作。Python 中参数的传递都是“引用传递”,不 是“值传递”。

1. 对可变对象(例如:列表、字典、自定义的其他可变对象等)进行“写操作”,直接作用于原对象本身。

b = [10,20]
def f2(m):
    print("m:",id(m)) #b 和 m 是同一个对象
    m.append(30)      #由于 m 是可变对象,不创建对象拷贝,直接修改这个对象
f2(b)
print("b:",id(b))
print(b)

运行结果:
m: 2093378589064
b: 2093378589064
[10, 20, 30]

2. 对不可变对象(例如:int、float、字符串、元组、布尔值)进行“写操作”,会产生一个新的“对象空间”,并用新的值填 充这块空间

#传递不可变对象的引用
a = 100
def f1(n):
    print("n:",id(n))     #传递进来的是 a 对象的地址
    n = n+200             #由于 a 是不可变对象,因此创建新的对象 n
    print("n:",id(n))     #n 已经变成了新的对象
    print(n)
f1(a)
print("a:",id(a))

运行结果:
n: 140718658465264    
n: 1477604705872        #n值改变后,地址也变化了,所以是新建的对象
300
a: 140718658465264

浅拷贝和深拷贝

浅拷贝(copy):不拷贝子对象的内容,只是拷贝子对象的引用。

深拷贝(deepcopy):会连子对象的内存也全部拷贝一份,对子对象的修改不会影响源对象

import copy
def t_Copy():
    '''测试浅拷贝'''
    a = [10, 20, [5, 6]]
    b = copy.copy(a)
    print("a", a)
    print("b", b)
    b.append(30)
    b[2].append(7)
    print("浅拷贝......")
    print("a", a)
    print("b", b)
def t_DeepCopy():
    '''测试深拷贝'''
    a = [10, 20, [5, 6]]
    b = copy.deepcopy(a)
    print("a", a)
    print("b", b)
    b.append(30)
    b[2].append(7)
    print("深拷贝......")
    print("a", a)
    print("b", b)

t_Copy()
print("*"*20)
t_DeepCopy()

a [10, 20, [5, 6]]
b [10, 20, [5, 6]]
浅拷贝......
a [10, 20, [5, 6, 7]]             #b引用了a的子对象,所以改变b时会影响到对象a的变化
b [10, 20, [5, 6, 7], 30]     
********************
a [10, 20, [5, 6]]
b [10, 20, [5, 6]]
深拷贝......
a [10, 20, [5, 6]]               #b相当于创建了一个跟a的值一样的新对象,所以改变b的值不会影响a
b [10, 20, [5, 6, 7], 30]

传递不可变对象包含的子对象是可变的情况

#传递不可变对象时。不可变对象里面包含的子对象是可变的。则方法内修改了这个可变对象,源对象也发生了变化。(类似于浅拷贝)
a = (10,20,[5,6])
print("a:",id(a))
def t01(m):
    print("m:",id(m))
    m[2][0] = 888
    print(m)
    print("m:",id(m))
t01(a)
print(a)

运行结果:
a: 41611632
m: 41611632
(10, 20, [888, 6])
m: 41611632
(10, 20, [888, 6])

函数的参数的类型

位置参数 :实参默认按位置顺序传递,需要个数和形参匹配

默认值参数 :我们可以为某些参数设置默认值,这样这些参数在传递时就是可选的。 默认值参数必须放到位置参数后面

命名参数 :我们也可以按照形参的名称传递参数,称为“命名参数”,也称“关键字参数”。

#参数的类型:位置参数、默认值参数、命名参数、可变参数
#测试位置参数
def f1(a,b,c):
    print(a,b,c)
f1(2,3,4)            #位置参数,形参与实参的值一一对应
#f1(2,3)              #报错,参数个数不匹配
f1(c=1,a=2,b=3)      #命名参数,按参数名来传递值

def f2(a,b,c=10,d=20):   #c和d是默认值参数
    print(a,b,c,d)
f2(8,9)                #在调用函数时,默认参数的值可不填
f2(8,9,11)

可变参数:指的是“可变数量的参数”。分两种情况:

                  1. *param(一个星号),将多个参数收集到一个“元组”对象中。

                  2. **param(两个星号),将多个参数收集到一个“字典”对象中。

def f1(a,b,*c):      #带一个*的可变参数,对应的是元组
    print(a,b,c)
f1(8,9,19,20)        #结果:8 9 (19,20)
def f2(a,b,**c):     #带**的可变参数,对应的是字典
    print(a,b,c)
f2(8,9,name='gaoqi',age=18)    #结果:8 9 {'name': 'gaoqi', 'age': 18}

强制命名参数:在带星号的“可变参数”后面的参数,必须在调用的时候强制命名的参数

def f1(*a,b,c):
    print(a,b,c)
#f1(2,3,4)         #会报错。由于 a 是可变参数,将 2,3,4 全部收集。造成 b 和 c 没有赋值。
f1(2,b=3,c=4)      #结果:(2,) 3 4

lambda 表达式

lambda 表达式可以用来声明匿名函数,lambda 函数实际生成了一个函数对象。lambda 表达式只允许包含一个表达式,该表达式的计算结果就是函数 的返回值

#lambda 表达式使用
f = lambda a,b,c:a+b+c
print(f)                                #f是lambda对象
print(f(2,3,4))                         #返回值就是表达式的计算结果
g = [lambda a:a*2,lambda b:b*3,lambda c:c*4]
print(g[0](6),g[1](7),g[2](8))          #结果:12 21 32

eval()函数

功能:将字符串 str 当成有效的表达式来求值并返回计算结果。

#测试 eval()函数
s = "print('abcde')"
eval(s)            #结果:abcde
a = 10
b = 20
c = eval("a+b")    #结果:30
print(c)
dict1 = dict(a=100,b=200)
d = eval("a+b",dict1)   #从dict1函数中调用参数a和b,并计算a+b的值
print(d)                #结果:300

NOTE:eval 函数会将字符串当做语句来执行,因此会被注入安全隐患。比如:字符串中含有删除文 件的语句。那就麻烦大了。因此,使用时候,要慎重!!!

递归函数

递归函数指的是:自己调用自己的函数,在函数体内部直接或间接的自己调用自己.。 每个递归函数必须包含两个部分:

   1. 终止条件

       表示递归什么时候结束。一般用于返回值,不再调用自己。

   2. 递归步骤

       把第 n 步的值和第 n-1 步相关联。

#使用递归函数计算阶乘(factorial)
def factorial(n):
    if n==1:       #结束条件
        return 1
    else:
        return n*factorial(n-1)   #递归步骤
for i in range(1,6):              #计算1~6的阶乘
    print(i,'!=',factorial(i))

嵌套函数(内部函数)

嵌套函数: 在函数内部定义的函数!

#测试嵌套函数
def f1():
    print('f1 running...')
    def f2():
        print('f2 running...')
    f2()
f1()

运行结果:
f1 running... 
f2 running...

nonlocal 关键字

nonlocal 用来声明外层的局部变量。

global 用来声明全局变量。

#测试 nonlocal、global 关键字的用法
a=100
def outer():
    b = 10
    def inner():
        nonlocal b   #声明外部函数的局部变量
        print("inner b:",b)   #inner b:10
        b = 20           #给外部函数的局部变量赋值
        global a         #声明全局变量
        a = 1000         #给全局变量赋值
    inner()
    print("outer b:",b)       #outer b:20
outer()
print("a:",a)                 #a:1000

LEGB 规则

Python 在查找“名称”时,是按照Local-->Enclosed-->Global-->Built in 的顺序来找的

Local 指的就是(函数或者类的方法内部的)局部变量

Enclosed 指的是嵌套函数(一个函数包裹另一个函数,闭包)

Global 指的是模块中的全局变量

Built in 指的是 Python 中的内置函数。

#测试 LEGB
str = "global"
def outer():
    str = "outer"
    def inner():
        str = "inner"
        print(str)
    inner()
outer()

#依次从内而外将几个 str 注释掉,观察控制台打印的内容

 

 

 

 

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_42119837/article/details/109083755

智能推荐

制作天空盒及将天空盒的场景反映在材质上_游戏开发 透明材质 天空盒拖影-程序员宅基地

文章浏览阅读2.2k次。1.新建一个项目,将全景图片拖动到项目中2.选中两张图片,然后在Texture Shape 中选择Cube,然后点击Apply3.创建一个Material,在Shader中选择Skybox/Cubemap,4.选中一张图片,这样就制作成功了一个天空盒 5.点击Window--Lighting--Settings,弹出天空盒的弹框、6.给Skybo_游戏开发 透明材质 天空盒拖影

算法-动态规划2图问题-多段图的最短路径问题_怎么将有向图分为互不相交的子集-程序员宅基地

文章浏览阅读1.3k次。算法-动态规划2-多段图的最短路径问题多段图的最短路径问题问题:设图G=(V,E)是一个带权有向图,如果把顶点集合V划分成k个互不相交的子集Vi(2<=k<=n,1<=i<=k),使得E中的任何一条边<u,v>,必有u∈Vi, v∈Vi+m(1<=i<k,1<i+m<=k),则称图G为多段图,称s∈V1为源点, t∈Vk为终点。多段图的最短路径问题为从源点到终点的最小代价路径。..._怎么将有向图分为互不相交的子集

自由落体_在高为 h 的天花板上有 n 个小球,体积不计,位置分别为 0,1,2,….n-1。在地面上有-程序员宅基地

文章浏览阅读770次。自由落体题目描述在高为H的天花板上有n个小球,体积不计,位置分别为 0,1,2,…,n-1,在地面上有一个小车(长为L,高为K,距原点距离为S1)。已知小球下落距离计算公式为d=d=0.5×g×t^2,其中 g=10,t为下落时间。地面上的小车以速度V前进。如下图:小车与所有小球同时开始运动,当小球距小车的距离 ≤0.0001时,即认为小球被小车接受(小球落到地面后不能被接受)。请你计算..._在高为 h 的天花板上有 n 个小球,体积不计,位置分别为 0,1,2,….n-1。在地面上有

日常报错记录_parse attempt failed for value-程序员宅基地

文章浏览阅读874次。报错java.lang.NullPointerException: nulljava.lang.NullPointerException: nulljava.lang.NullPointerException: null at com.bootdo.hrms.controller.DepartmentManagementController.list(DepartmentManagementController.java:66) ~[classes/:na] at com.bootdo.hrms.c_parse attempt failed for value

Vue基于ElementUI的Dialog实现弹窗登录,登录成功前不允许关闭_dialog实现的登录-程序员宅基地

文章浏览阅读7.5k次。业务场景当页面比较单一,只是个单页面的时候。优点简单粗暴1.使用了session来记录登录是否成功,成功后不需要再登录;2.使用最简单的方式,可以写死用户,不需要有后台服务,当然也可以修改代码从后台校验用户登录;3.使用回调函数来强制用户不能点击空白处也不能关闭该登录窗口。缺点这里只是简单实现,不适合复杂业务场景代码新建一个vue组件,代码如下,把这个组件引入到你的页面,就会自..._dialog实现的登录

随便推点

Native Instruments Maschine 2 Factory Library Mac(预置音色库)_native instruments - maschine 2 factory library v1-程序员宅基地

文章浏览阅读322次。Native InstrumentsMaschine 2 Factory Library Mac是一款由著名的声音设计师和艺术家创建的预置音色库。Maschine 2 Factory Library Mac版可让您通过强大的鼓合成器、优质声音、集成采样器等轻松制作节拍、旋律和和声,以真正无与伦比的质量创建自己完美调音的电子和声学鼓声。传送门:https://mac.orsoon.com/Mac/185379.htmlNative Instruments Maschine 2 Factory..._native instruments - maschine 2 factory library v1.3.9 (battery, kontakt, ma

Implicit 3D Orientation Learning for 6D Object Detection from RGB Images-程序员宅基地

文章浏览阅读1.6k次,点赞2次,收藏7次。从RGB图像中进行6D目标检测的隐式三维方向学习论文是我自己翻译的,限于本人的水平,不到之处请多包涵摘要:我们提出了一种基于RGB的实时管道[1],用于物体检测和6D姿态估计。我们新颖的3D方向估计基于去噪自动编码器的变体,该变体使用域随机化在3D模型的模拟视图上训练。这种所谓的增强自动编码器与现有方法相比具有几个优点:它不需要真实的,带有姿势注释的训练数据,可以推广到各种测试传感器,并且固..._implicit 3d orientation learning for 6d object detection from rgb im- ages.

五天带你学完《计算机网络》,期末考试不挂科_计算机网络不挂科csdn-程序员宅基地

文章浏览阅读9.2k次,点赞50次,收藏432次。欢迎广大学子报考河北师范大学软件工程专业!!!!!!!!本系列文章基于谢希仁《计算机网络》第五版教材并根据上课记录整理而成。感谢各位读者一直以来对于笔者的大力支持!_计算机网络不挂科csdn

C语言如何在一个.c源文件里调用另一个源文件中的函数_c语言调用另一个.c文件中的方法-程序员宅基地

文章浏览阅读2.9w次,点赞27次,收藏145次。对于C语言来说main函数是程序的入口,当我们要开发一个比较大的程序时,可能会有很多代码,这时候想要为了方便维护通常都采取模块开发,将不同类的模块写到不同的文件中首先定义一个.h的头文件,如function.h,在里面声明将要实现的函数,如int add(int a,int b);然后新建一个源文件为function.c,在function.c的开头添加#include "function..._c语言调用另一个.c文件中的方法

unity中地形Terrain明显闪烁的解决办法_unity 草和地形 闪烁-程序员宅基地

文章浏览阅读3.2k次,点赞3次,收藏7次。新人们经常会遇到一个问题,有时候unity中地形Terrain与其它模型的mesh有重叠的地方会出现明显闪烁。研究了一下,Clipping Planes的取值会严重影响unity自带地形Terrain的渲染,Near值越小,Terrain与其它模型交接面的闪烁现象就越严重。这可能是一个BUG,以后Near值建议取0.9以上。_unity 草和地形 闪烁

无人车系统(四):轨迹跟踪PID控制_tracking pid 循迹追踪-程序员宅基地

文章浏览阅读4.9w次,点赞97次,收藏654次。本篇介绍如何利用PID控制实现无人车轨迹跟踪。1. 横向跟踪误差横向跟踪误差(cross track error, 简称CTE)为前轴中心点(rx,ry)(r_x, r_y)(rx​,ry​)到最近路径点(px,py)(p_x, p_y)(px​,py​)的距离,具体如下图所示。以上图为基础进行简略分析,如果参考轨迹点在无人车的左边θe∈[0,π]\theta_{e}\in [0, \......_tracking pid 循迹追踪

推荐文章

热门文章

相关标签