文章目录
Python基础-函数
1.引子:
分别求1-15,23-65,253-685的和
def sum(m,n):
sum=0
for i in range(m,n+1):
sum+=i
print(sum)
sum(1,15)
sum(12,36)
sum(55,68)
对程序而言:函数是对程序逻辑进行结构化或者过程化的一种编程方法。
built-in function 内置函数 —>BIF
2.函数定义:
声明函数的一般形式:
def function_name(arg1,arg2,...,argn):
'''statements''' #函数功能,可以使用dunction_name._doc_调用
func_statements #函数体
return value #返回值
说明如下:
1.函数代码块以 def 关键词开头,后接函数标识符名称和小括号 ()。
2.任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
3.函数的第一行语句可以选择性地使用文档字符串----用于存放函数说明。
4.函数内容以冒号起始,并且缩进。
5.return [表达式] 结束函数,选择性的返回一个值给调用方。不带表达式的return相当于返回 None。
其中参数列表和返回值不是必须的,return后也可以不跟返回值,甚至连 return也没有。
对于return后没有返回值的和没有return语句的函数都会返回None值
有些函数可能既不需要传递参数,也没有返回值。
没有参数时,包含参数的圆括号也必须写上,圆括号后也必须有“:”。
3.函数调用
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
格式:
def fc():
print('hello')
fc()
4.函数文档说明
用于向别人解释函数的功能,用法,以及参数
可用 f.__doc__调用说明
def foo():
'foo() --- Properly created doc string.'
def bar():
pass
bar.__doc__='Oops,forget the doc str above'
print(foo.__doc__,bar.__doc__)
'''
foo() --- Properly created doc string. Oops,forget the doc str above
'''
5.函数参数
- 不传参函数
- 传参函数
- 顺序
6.函数返回值
使用return语句为函数增加返回值
def sum(x,y):
return x+y
print(sum(1,2))
'3'
7.函数的参数种类
1. 形参
只有在调用时才分配内存单元,调用结束后,释放所分配的内存单元。因此形参只在函数内部有效,函数调用结束返回主调用函数后不能再使用该形参变量。
2.实参
为一个确定的值,能够传递给形参,作为位置参数或者关键字参数传递
3. 位置参数
def usr_manage(name,age,job,hobby):
print('用户管理系统'.center(16,'-'))
print('\tName:\t',name)
print('\tAge:\t',age)
print('\tJob:\t',job)
print('\tHobby:\t',hobby)
usr_manage('jack',20,'IT','reading')
usr_manage('Nico',18,'Stu','Gameing')
# 值传递实参,位置一一对应 --->位置参数
#使用位置参数时和函数头定义的形参在顺序,个数,类型上匹配
'''
-----用户管理系统-----
Name: jack
Age: 20
Job: IT
Hobby: reading
-----用户管理系统-----
Name: Nico
Age: 18
Job: Stu
Hobby: Gameing
'''
4.默认值参数
当对应形参无输入时,使用默认值作为输出
def usr_manage(name='bill',age='35',job='panter',hobby='swimming'):
print('用户管理系统'.center(16,'-'))
print('\tName:\t',name)
print('\tAge:\t',age)
print('\tJob:\t',job)
print('\tHobby:\t',hobby)
usr_manage()
'''
-----用户管理系统-----
Name: bill
Age: 35
Job: panter
Hobby: swimming
'''
默认值参数,关键字参数必须放置于位置参数之后
5.不定参数
在Python中指* args和**kwargs两个魔法变量,主要用于函数定义,我们可以将不定数量的参数传递给一个函数。
#魔法变量在最前面,最后面和中间
*a,b,c=1,2,3,4,5
print(a,b,c)
a,b,*c=1,2,3,4,5
print(a,b,c)
a,*b,c=1,2,3,4,5
print(a,b,c)
'''
[1, 2, 3] 4 5
1 2 [3, 4, 5]
1 [2, 3, 4] 5
'''
#*args 用来接受任意飞键值对任意数量的参数列表给函数,返回值为一个元组
def uncertain_para(para,*args):
print('普通位参数: ',para)
print('不定参数:',args)
print(type(args))
uncertain_para(1,2,3,4,5)
'''
[1, 2, 3]
普通位参数: 1
不定参数: (2, 3, 4, 5)
<class 'tuple'>
'''
#**kwargs 接收任意不定长度的键值对列表给函数
def un_para_key(**kwargs):
print(kwargs) #返回值为字典
print(type(kwargs))
un_para_key(a=1,b=2,c=3)
un_para_key()
'''
{'a': 1, 'b': 2, 'c': 3}
<class 'dict'>
{}
<class 'dict'>
'''
def un_para_key(x,y,*z,**kwargs):
print(x,y,z)
print(kwargs)
un_para_key(1,2,3,'d','e',a=1,b=2,c=3)
'''
1 2 (3, 'd', 'e')
{'a': 1, 'b': 2, 'c': 3}
'''
8.函数引用
调用其他模块的函数
import random
i=random.random(10)
9.函数属性
函数属性时Python中另外一个使用了句点属性标识并拥有名字的属性
10.内嵌函数
内嵌函数只能在被嵌入函数内调用
def foo():
def bar(): #bar()函数全部处于外部foo()函数的作用域内
print('bar() called.')
print('foo() called')
bar()
foo()
bar() #在foo()函数外部调用bar()报错
'''
foo() called
bar() called.
File "D:/PycharmProject/day07/函数.py", line 101, in <module>
bar()
NameError: name 'bar' is not defined
'''
11.作用域
Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。
1.作用域的产生
当变量在module,class,函数中定义时才会有作用域的概念
def foo():
a='foo' #在foo()中定义a 一般只在foo()中能够调用
print(a)
print(a)
'''
Traceback (most recent call last):
File "D:/PycharmProject/day07/函数.py", line 108, in <module>
print(a)
NameError: name 'a' is not defined
'''
在作用域中定义的变量,一般只在作用域内有效,但在if-elif-else,for-else,while-else,try-except(else-finally)不会产生定义域
if True:
a=100
print(a)
'100'
2.作用域的类型
Python使用一个变量时,并不要求预先声明它。但在真正使用的时候,它必须绑定到某个内存对象(被定义,被赋值)。这种变量名的绑定将在当前作用域引入新的变量,同时屏蔽外层作用域中的同名变量。
-
局部作用域(local–>L)
局部变量:包含在def,class,module关键字定义的语句块中,即在函数,类,模块中定义的变量。每当函数被调用时都会创建一个新的局部作用域。Python中也有递归,即自己调用自己,每次调用都会创建一个新的局部命名空间。在函数内部的变量声明,除非特别的声明为全局变量,否则均默认为局部变量。有些情况需要在函数内部定义全局变量,这时可以使用global关键字来声明变量的作用域为全局。局部变量域就像一个 栈,仅仅是暂时的存在,依赖创建该局部作用域的函数是否处于活动的状态。所以,一般建议尽量少定义全局变量,因为全局变量在模块文件运行的过程中会一直存在,占用内存空间。
-
嵌套作用域(enclosing—>E)
嵌套作用域:也包含在def,E和L是相对的,E相对于更上层的函数而言也是一个局部作用域。与L的区别在于,对于一个函数而言,L是定义在此函数内部的局部作用域。主要是为了实现Python的闭包
-
全局作用域(Global—>G)
即在模块层次中定义的变量。模块顶层声明的变量具有全局作用域从外部来看,模块的全局变量就是相当于模块变量的属性。
-
内置作用域(built-in —>B)
系统内置模块中定义的变量
搜索优先级:局部作用域>嵌套作用域>全局作用域>内置作用域
12.全局变量与局部变量
全局变量:
gbl_str='foo' #全局变量
def foo():
loc_str='bar' #局部变量
return gbl_str+loc_str #foo()可以访问全局变量
print(foo())
print(gbl_str)
# print(loc_str)
a=123
b=9999
def foo():
a=666
print('foo(),修改前:',a)
#当a=666被注释掉时,由于能够在foo()中找到a所以不会使用全局变量的a,由于a定义在print()之后,报错
a=888
print('foo(),修改后:',a)
print('b:',b) #foo()可以访问全局变量
def bar():
a=6688
print('bar(),a:',a)
print('bar(),b:',b) #bar()可以访问全局变量
foo()
bar()
print(a)
'''
foo(),修改前: 666
foo(),修改后: 888
b:9999
bar(),a: 6688
bar(),b: 9999
123
'''
13.递归函数
在一个函数体内部,调用函数本身
def func(n): #斐波那契数列
if n==1:
return 1
elif n ==2:
return 1
else:
return func(n-2)+func(n-1) #调用func函数本身,直到n=2,n=1
print(func(10))
'55'
def func(n):
print(n)
if int(n/2)==0:
return n
return func(int(n/2))
print(func(10),end=' ')
'10,5,2,1,1'
14.匿名函数(lambda)
一般用于比较简单的函数表达式
- 格式:
lambda para1, para2,..., paran:expression using paras
demo:
f = lambda x, y, z: x+y+z
'''
def f(x,y,z):
return x+y+z
'''
print(type(f))
print(f(1, 2, 3))
'''
<class 'function'>
6
'''
f = lambda x = 'z', y = 'u',z = 'cc':x+y+z
print(f())
'zucc'
15.高阶函数
把一个函数名,以实参的形式,传递给这个函数的形参
def add(a, b, c):
return c(a) + c(b)
print(add(-9, 1, abs)) # return abs(-9)+abs(1)
'10'
def pow(x):
return x**2
def add(a, b, func):
return func(a) + func(b)
a_value = add(-9, 1, pow) #return -9**2+1**2
print(a_value)
82
li = ['Zhejiang', 'University', 'City', 'College']
def filter_test1(para):
ret = []
for i in para:
if not i.startswith('C'): #判断第一个字符是否为C
ret.append(i)
return ret
def filter_test2(para):
ret = []
for i in para:
if not i.endswith('ty'): #判断最后两个字符是否为ty
ret.append(i)
return ret
def test(a,func,func1):
return func1(func(a)) #把func()作为func1()的参数输入
zzz = test(li, filter_test1,filter_test2)
print(zzz)
['Zhejiang']
16.filter 函数
li = ['Zhejiang', 'University', 'City', 'College']
f1 = filter(lambda sr: not sr.endswith('ty'),li)
print(list(f1))
['Zhejiang', 'College']
功能:
-
过滤掉序列中不符合函数条件的元素。当序列中要需要保留的元素可以用某些函数描述时,就应该想到filter函数
-
filter(function,sequence)
- function —> 可以是自定义的函数,也可匿名函数
- sequence —> 列表,元组,字符串
17.map(映射)函数
求一个序列或多个序列进行函数映射后的值。返回值需要用list强转一下(listmap())
格式
map(function,iterable1,iterable2,...,literablen)
#function的参数可以不止一个
#iterable为传入function的参数
demo:
x=[1,2,3,4,5]
y=[2,3,4,5,6]
res=map(lambda x, y : x*y + 2 , x, y)
print(list(res))
def f(a,b):
return a*b+2
res=map(f,x,y)
print(list(res))
'''
[4, 8, 14, 22, 32]
[4, 8, 14, 22, 32]
'''
18.raduce函数
对一个序列进行压缩运算,得到一个值(value).在Python3中它被移植到了functools模块中.
#导入
import functools
from functools import reduce
#常用格式
reduce(function,iterable,[initial])
#function 必须传入两个参数
#iterable 为元组或者列表
demo:
from functools import reduce
y=[1,2,2,3,3,3]
z=reduce(lambda x,y:x+y,y)
'''
1 1+2=3 [3,2,3,3,3]
2. 3+2=5 [5,3,3,3]
3 5+3=8 [8,3,3]
4 8+3=11 [11,3]
5 11+3=14 14
'''
print(z)
'14'
#把给的序列值转换成一个数字
from functools import reduce
y=[1,2,2,3,3,3]
z=reduce(lambda x,y:10*x+y,y)
'''
1 1+2=3 [3,2,3,3,3]
2. 3+2=5 [5,3,3,3]
3 5+3=8 [8,3,3]
4 8+3=11 [11,3]
5 11+3=14 14
'''
print(z)
'122333'
from functools import reduce
y=[1,2,2,3,3,3]
z=reduce(lambda x,y:10*x+y,y,100)
'''
1 1+2=3 [3,2,3,3,3]
2. 3+2=5 [5,3,3,3]
3 5+3=8 [8,3,3]
4 8+3=11 [11,3]
5 11+3=14 14
'''
print(z)
'100122333' #说明第二个参数是加在序列的第1位上
19.apply函数
存在于pandas中,应用对象是pandas库中的DataFrame或者Series,直接对DataFrame或者Series应用函数或者对pandas中的groupby之后的聚合对象使用
20.zip函数
将一个可迭代对象作为参数,将对象中对映的元素打包成一个个元组,返回有这些元组构成的对象
长度不一致以短的为主
注释:用*操作符,与zip相反进行解压。
格式:
zip(iterable1,iterable2...,iterablen)
#iterable --->两个或多个可迭代对象(字符串,列表,元组,字典)
#在Python2中返回由元组组成的列表,Py3返回一个对象,若要得到列表,需进行转换
demo:
a=[1,2,3,4]
b=[4,5,6,7]
c=['x','y','z']
ziptest1=zip(a,b)
print(ziptest1)
for i in ziptest1:
print(i,end=' ')
print()
print(list(ziptest1))
print(list(zip(b,a)))
print(list(zip(b,c)))
print(list(zip(*ziptest1)))
print(ziptest1)
print(list(zip(a,b,c)))
print(list(zip({1:11,2:22,3:33},{4:44,5:55,6:66},{7:77,8:88,9:99})))
'''
<zip object at 0x0000000001E7D888>
(1, 4) (2, 5) (3, 6) (4, 7)
[] #进行一次取值后缓冲区被释放无法再次取值
[(4, 1), (5, 2), (6, 3), (7, 4)]
[(4, 'x'), (5, 'y'), (6, 'z')]
[]
<zip object at 0x0000000001E7D888> #可以看到ziptest1所对应的地址并没有发生变化
[(1, 4, 'x'), (2, 5, 'y'), (3, 6, 'z')]
[(1, 4, 7), (2, 5, 8), (3, 6, 9)] #字典支队键进行操作
'''
def is_palindrome(n):
if str(n)==str(n)[::-1]:
return n
else:
return
s=list(filter(is_palindrome,range(1,1000)))
s1=list(filter(lambda x:str(x)==str(x)[::-1],range(1,1000)))
print(s)
print(s1)
'''
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292, 303, 313, 323, 333, 343, 353, 363, 373, 383, 393, 404, 414, 424, 434, 444, 454, 464, 474, 484, 494, 505, 515, 525, 535, 545, 555, 565, 575, 585, 595, 606, 616, 626, 636, 646, 656, 666, 676, 686, 696, 707, 717, 727, 737, 747, 757, 767, 777, 787, 797, 808, 818, 828, 838, 848, 858, 868, 878, 888, 898, 909, 919, 929, 939, 949, 959, 969, 979, 989, 999]
'''