python语法(五)函数

1.什么是函数

对函数大概有个了解
函数的意义: 把具有独立功能的代码块组织为一个小模块,在需要的时候 调用
函数的作用:在开发程序时,使用函数可以提高编写的效率以及代码的重用
比如:

有 a = 4, b = 6, c = 45
三个数,要将这三个数进行以下操作
1.加一
2.乘10
3.减20
4.除以5
5.如果这时这个数大于0,求它的阶乘。
可以利用前面学习的语句进行处理,但是代码可以分析,这三个数需要的操作是一样的,将这些操作封装成函数后,可以缩减代码量。

函数的基本使用
函数的参数
函数的返回值
函数的嵌套调用
在模块中定义函数

2.函数的定义和调用

基本语法:

def 函数名():
	函数封装的代码
	……………………
函数基本规则
1.def 是 define 的缩写 定义
2.函数名称 应该能够表达函数封装代码的功能,方便后续的调用
3.函数名称的命名应该 符合标识符的命名规则
❤️.1可以由字母,下划线和数字组成
❤️.2不能以数字开头
❤️.3不能与关键字重名

函数的调用:
注意:定义好函数之后,只表达这个函数封装了一段代码而已
如果不主动调用函数,函数是不会主动执行的

def test():
	print(123)

test() #即可调用 , 函数名(参数列表) 即可调用函数

3.函数传递参数

演练:
开发一个 sum_2_num 的函数
函数能够实现两个数字的求和

def sum_2_num():
	num1 = 10
	num2 = 10
	result = num1 + num2
	print("%d + %d  = %d " % (num1,num2,result))

如果要实现任意两个数字之和就需要参数了
参数:在调用函数的时候,把外部的数据以参数的形式传递给函数,函数收后就可以在函数内部使用了

def sum_2_num(num1,num2):  #多个参数用' ,' 分割, num1,num2 是形参
	result = num1 + num2
	print("%d + %d  = %d " % (num1,num2,result))

sum_2_num(5,6) 5,6 叫实参

❤️.形参:定义函数时,小括号中的参数,是用来接收参数用的,在函数内部作为变量使用
❤️.作用:告诉外部,函数需要几个参数,在函数内部当变量使用
❤️.实参:调用函数时,小括号中的参数,是用来把数据传递到函数内部 用的

4.默认参数

❤️.默认参数:应该放到参数列表最后面
❤️.缺省参数:调用函数时,缺省参数的值如果没有传入,则被认为是默认值

def test(a,b,c,d=3.5,e = 100):
      print(a)
      print(b)
      print(c)
      print(d)
      print(e)

因为可以设置默认参数,所以在调用函数的时候,传参就变得多元化

test(1,2,3,4,5)
test(1,2,3,4)
test(1,2,3)

补充:

’‘’
def test1(a,b):
      print(a)
      print(b)
test1(b = 11, a = 22)
‘’‘
test(a = 1,b = 2, c = 3, d = 4,e = 5)
#可以打乱顺序
test(a = 1,c = 2, b = 5, e = 7,d  = 6)

5.不定长参数

❤️.tes(a,b) 只能传入两个参数
❤️.tes(a,b,c = 1,d = 2) 能传入2~4个参数,多传入就会报错
如果想要传递任意长度的参数

def test(a,b,*args,**kwargs):
       print(a)
       print(b)
       print(args)
       print(kwargs)

test(10,1,2,3,4,5,6,7,8,9,7,5,4,2,2,2,2,2,n = 20,m = 30)
运行结果:
10
1
(2, 3, 4, 5, 6, 7, 8, 9, 7, 5, 4, 2, 2, 2, 2, 2)
{'n': 20, 'm': 30}

这里算是规定:
❤️.当a与b匹配过后,剩下的就按照 类似于 n = 20(key = value)这样的传给 **kwargs,其他的就传给 *args
也可以 传入一些序列:

A = [10,20,30]
B = {'a' : 1,'b' :2}
test(1,2,1,2,1,A,B)
结果为:
1
2
(1, 2, 1, [10, 20, 30], {'a': 1, 'b': 2})
{}
test(1,2,1,2,1,*A,*B)
结果为
1
2
(1, 2, 1, 10, 20, 30, 'a', 'b')
{}

解释:
#当列表/元组在当做实参传递的时候,如果前面有一个*, 表示对其进行解包
#意思是:[111,222,333] ---------> 111,222,333
#当字典当作一个实参进行传递的时候,如果前面有两个*,表示对其进行解包
#意思是:{‘aa’:100,“bb”:200} ------> aa = 100, bb = 200

6.函数的返回值

❤️.在程序开发中,有时候,会希望一个函数结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理
❤️.返回值是函数完成工作后,最后给调用者的 一个结果,在函数中使用 return 关键字可以返回结果做后续的处理

e.g:
def sum_2_num(num1,num2):
	return num1 + num2

result = sum_2_num(10,20)
print("计算结果是 %d " % result)

7.函数的四种类型:

❤️.无参数,无返回值
此类函数,不能接收参数,也没有返回值,一般情况下,就用来打印内容。

def Prints():
	print("-------菜单---------")

❤️.无参数,有返回值
此类函数,不能接收参数,但是可以返回某个数据,一般情况下,像采集数据,用此类函数。

def getnum():
	return 123

❤️.有参数,无返回值
此类函数,能接收参数,但不可以返回数据,一般情况下,对某些变量设置数据而不需要结果时,用此类函数
❤️.有参数,有返回值
此类函数,不仅能接收参数,还可以返回某个数据,一般情况下,像数据处理并需要结果的应用,用此类函数

8.函数的嵌套

def testB(): 
       pass
def testA():
       testB()
testA()

9.变量的作用域

python内存管理机制
❤️.python中一切皆对象
Python中对象包含的三个基本要素,分别是:id(身份标识)type(数据类型)value(值)
Python中的所有对象都有三个特点:
身份:每个对象都有一个唯一的身份标识自己,任何对象的身份都可以使用内建函数id()来得到,可以简单的理解为这个值式对象的内存地址
类型:对象的类型决定了对象可以保存什么类型的值,有哪些属性和方法,可以进行哪些操作,遵循怎样的规则。可以使用内建函数type() 来查看对象的类型
:对象所表示的数据
Python 中的一切都可以赋值给变量或者作为参数传递给函数。
❤️.python中的可变对象和不可变对象
python中对象可分为:可变对象不可变对象
不可变对象:对象所指向的内存中的值不能被改变,当改变这个变量的时候,原来指向的内存中的值不变,变量不再指向原来的值,而是开辟一块新的内存,变量指向新的内存。
不可变:int、字符串(str)、float、(数值型number)、元组(tuple)、None(空)
可变对象:对象存放在地址中的值会原地改变
可变:字典型(dictionary)、列表型(list), set(集合)
命名空间: 就是一个名字起作用的空间,生效的范围
比如有一个学校,有10个班级,在七班和八班中都有一个叫“小王”的同学,如果在学校的广播中呼叫“小王”时,七班和八班中的这两个人就纳闷了,如果是呼喊“七班的小王”的话,那么就很明确了,那么此时的七班就是小王所在的范围,即命名空间
作用:规定了访问范围
e.g:

进入ipython的界面其实那个界面内就是一个空间。
在ipyhton 中 如果不导入包 就没办法调用其他空间的函数
import test
from test import *

❤️.一个命名空间又包括了 globals, locals.(全局变量,局部变量)

a = 100#全局变量
def test():
	b = 200 #局部变量
globals()
可以得到系统全局变量
locals()
def test():
	a = 1
	b = 2
	c = 3
	print(locals()) #得到函数中的局部变量

❤️.LEGB 规则:
通常而言,在编程语言java和C中,变量的作用域从代码结构形式来看,有块级、函数、类、模块、包等由小到大的级别。但是在Python中,没有块级作用域,也就是类似if语句块、for语句块、with上下文管理器等等是不存在作用域概念的,他们等同于普通的语句。if语句中的变量可以在if外使用。
python 使用LEGB 的顺序来查找一个符号对应的对象

locals -> enclosing function -> globals -> builtins

locals: 当前所在命名空间(如函数,模块),函数的参数也属于命名空间内的变量
enclosing: 外部嵌套函数的命名空间(闭包中常见)

def fun1():
	a = 10;
	def fun2():
		# a 位于外部嵌套函数的命名空间
		print(a)

globals: 全局变量,函数定义所在模块的命名空间

a = 1
def fun():
	#需要通过 global 指令来声明全局变量
	global a
	#修改全局变量,而不是创建一个新的 local 变量
	a = 2

Builtins: Python内置模块的名字空间
❤️.Python 在启动的时候会自动为我们载入很多内建的函数、类,比如 dict,list,type,print,这些都位于 __ builtin__ 模块中, 可以使用 dir(__ builtin__) 来查看。这也是为什么我们在没有 import任何模块的情况下,就能使用这么多丰富的函数和功能了。
❤️.在Python中,有一个内建模块,该模块中有一些常用函数;在Python启动后,且没有执行程序员所写的任何代码前,Python会首先加载该内建函数到内存。另外,该内建模块中的功能可以直接使用,不用在其前添加内建模块前缀,其原因是对函数、变量、类等标识符的查找是按LEGB法则,其中B即代表内建模块比如:内建模块中有一个abs()函数,其功能求绝对值,如abs(-20)将返回20。

10.局部变量

e.g:
import time
def test1():
	num = 100  // 局部变量
	print(num)
def test2():
	num = 200// 局部变量
	print(num)
	time.sleep(1)
	num = num  + 100
	print(num)
1.test1()
2.test2()

在函数内部定义的变量就是局部变量。
局部变量,意思就是只作用于局部范围。以函数为例子,在函数内部定义的变量作用范围就只在函数内函数调用结束,就会自动释放其空间

11.全局变量

num = 100
def test1():
	print(num)
def test2():
	print(num)

特性:全局变量可以在函数中直接使用,但是不能改变值(针对不可变类型)

def test1():
	#如果在函数中直接修改全局变量,那么会产生异常
	#如果真的需要进行修改,那么可以在函数里面进行声明 
	global num
	print(num)
	num+=2
	print(num)
test2() 和 test()1 输出的结果相同

12.递归函数

❤️.设置递归深度

import sys
sys.setrecursionlimit(1000000000)

递归解释:一个函数在内部调用自己本身,这个函数就是递归函数。比如要得到一个数的阶乘

def gets(u):
	if u == 1:
		return 1
	return u*gets(u-1)

斐波拉契递归做法:

def fibolaqi(x):
    if(x==1):
        return 1
    if(x==2):
        return 1
    return fibolaqi(x-1) + fibolaqi(x-2)

13.匿名函数

lambda 表达式
举个例子

def eg(x):
      return 2 * x + 1

g = lambda x : 2 * x + 1

g(5) 的结果就是 11  了 与 eg(5)相同

两个参数的例子
g = lambda x,y : x + y
g(3,4) = 7

lambda表达式的作用:
用py写一些执行脚本时,使用lambda就可以省下来定义函数过程,比如说我们只是需要写个简单的脚本来管理服务器时间,我们就不用专门定义一个 函数然后在调用,使用lambda就可以使得代码更加简洁 .对于一些比较抽象并且整个程序执行下来只需要调用一两次的函数,有时候给函数取个名字也比较麻烦,使用lambda就可以有效解决这个问题了

14.时间函数

❤️.python 表示时间的方式有如下几种:
时间戳
时间元组
格式化的时间字符串
这三种表示时间的方式,都需要借助python中的time模块来实现。
时间戳:
时间戳表示的是从1970年1月1日 00:00:00开始按秒计算的偏移量
time 模块中返回时间戳的函数主要有time(),clock().

import time 
t_time = time.time()

时间元组
time模块中提供的用于返回时间元组的函数主要有 gmtime(),localtime()和strptime()。

import time
t_time = time.localtime()

t_time 是有九个元素的元组

索引字段
0tm_year四位数的年份 2008
1tm_mon表示月份,取值范围是1 ~ 12
2tm_mday表示月内的某一天,1~31
3tm_hour表示24小时制的小时数,取值范围是0~23
4tm_min表示分钟数,0~59
5tm_sec表示秒,取值范围是0~61(60或61是闰秒)
6tm_wday表示星期,取值范围是0~6(0是周一)
7tm_yday表示一年中的第几天,取值范围1~366
8tm_isdst决定是否为夏令时的标识符,取值是-1,0,1

格式化的时间字符串
可以使用time模块中的strftime方法来格式化时间字符串

strftime方法的格式化:
time.strftime(format[,t])
format --- 格式字符串
t--- t是一个时间元组

python中时间日期格式化符号:

符号解释
%y两位数的年份表示(00-99)
%Y四位数的年份表示(000-9999)
%m月份(01-12)
%d月内中的一天(0-31)
%H24小时制小时数(0-23)
%I12小时制小时数(01-12)
%M分钟数(00=59)
%S秒(00-59)
%a本地简化星期名称
%A本地完整星期名称
%b本地简化的月份名称
%B本地完整的月份名称
%c本地相应的日期表示和时间表示
%j年内的一天(001-366)
%p本地A.M.或P.M.的等价符
%U一年中的星期数(00-53)星期天为星期的开始
%w星期(0-6),星期天为星期的开始
%W一年中的星期数(00-53)星期一为星期的开始
%x本地相应的日期表示
%X本地相应的时间表示
%Z当前时区的名称
%%%号本身
 import time
 print(time.strftime("1. %Y-%m-%d %H:%M:%S",time.localtime()))
 print(time.strftime("2. %Y-%m-%d is %A",time.localtime()))
 print(time.strftime("3. 十二小时制时间是:%Y-%m-%d %I:%M:%S%p",time.localtime()))
 print(time.strftime("4. 现在是: %Z %c",time.localtime()))
 print(time.strftime("5. 现在是: %Z %a %b %d %I:%M:%S%p",time.localtime()))
 print(time.strftime("6. %Y-%m-%d是%B,这是%Y一年的第%j天",time.localtime()))
 # %U 一年中的星期数(00-53)星期天为星期的开始
 print(time.strftime("7. %Y-%m-%d是%A,这是%Y一年的第%U周",time.localtime(1607221844)))
 # %W 一年中的星期数(00-53)星期一为星期的开始
 print(time.strftime("8. %x是是%A,这是%Y一年的第%W周",time.localtime(1607221844)))
 print(time.strftime("9. 现在是:%Z %X%p",time.localtime()))
 
 --1. 2021-04-26 00:02:27
 --2. 2021-04-26 is Monday
 --3. 十二小时制时间是:2021-04-26 12:02:27AM
 --4. 现在是: 中国标准时间 Mon Apr 26 00:02:27 2021
 --5. 现在是: 中国标准时间 Mon Apr 26 12:02:27AM
 --6. 2021-04-26是April,这是2021一年的第116天
 --7. 2020-12-06是Sunday,这是2020一年的第49周
 --8. 12/06/20是是Sunday,这是2020一年的第48周
 --9. 现在是:中国标准时间 00:02:27AM

15.随机数函数

❤️.random 模块用于生成随机数:
获取0~1之间的随机浮点数,去值范围0 <= N <1

  random.random()

获取a和b之间的随机浮点数N,如果a < b,取值范围是 a<= N <= b.

  random.uniform(a,b)

获取a和b之间的随机整数,a < b,取值范围是 a <= N <= b

  random.randint(a,b)

获取序列sequence中随机的一个元素

  random.choice([1,2,3,4,5])

将列表中的元素打乱顺序,俗称“洗牌”

  demo_list = [1,2,3,4,5]
  random.shuffle(demo_list)

16.闭包

举个例子

def eg1(x):
      def eg2(y):
            return x * y
      return eg2

 i = eg1(5)

 这里的i就是eg2这个功能
 用type(i)可以得到 i 的类型 就是 function
 i(8)
 结果为
 40

也可eg1(5)(8),结果也是40,这就是闭包
例子2

def eg1():
	x = 2
	def eg2():
		x*=x
		return x
	return eg2()
eg1()

这样调用时会报错,提示在eg2中x 未定义这是py的机制

def eg1():
	x = [2]
	def eg2():
		x[0]*=x[0]
		return x[0]
	return eg2()

这样就可以了,原因是列表等是存在栈中,不会被马上清空,py3中有了改进nonlocal 关键字

def eg1():
	x = 2
	def eg2():
	        nonlocal x
		x*=x
		return x
	return eg2()

这样也解决了问题

补充:

❤️.两个比较厉害的BIF
1.filter()//又称过滤器
这个函数只有两个参数
第一个参数是 function 或者 None
第二个参数是 一个可迭代的迭代器
当第一个参数是None时
举个例子

list(filter(None,[[1,0,true,false]))

得到的列表的内容就是[1,true]
这个过滤器在第一个参数是None时的作用是过滤0,当第一个参数是function 时
举个例子,筛选出奇数的函数

def odd(x):
    return  x%2
temp = range(10)
show = filter(odd,temp)
list(show)
结果为 [1,3,5,7,9]

也可用lambda表达式

list(filter(lambda x : x % 2, range(10)))
结果为[1,3,5,7,9]

2.map()
将序列的每一个元素作为函数的参数进行运算加工直到可迭代序列的每个元素全都加工完毕返回所有加工后的元素构成的新序列
这个函数也有两个参数

list(map(lambda x : x * 2, range(10)))
得到的结果是[0,2,4,6,8,10,12,14,16,18]
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dearzcs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值