函数
引子
求 i1-i2 (如:1-15) 的和
def sum_of_num(i1,i2):
'''求和'''
sum = 0
for i in range(i1,i2+1):
sum+=i
return sum
print(sum_of_num(1,15))
120
程序而言:函数就是对程序逻辑进行结构化或者过程化的一种编程方法。
bulit-in function 内置函数 --> BIF
函数的定义
声明函数的一般形式:
def function_name(arg1,arg2, ... ,argn):
'''statements'''
func_statements
return Value
说明:
1.函数代码块以 def 关键词开头,后接函数标识符名称和小括号 ()。
2.任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
3.函数的第一行语句可以选择性地使用文档字符串----用于存放函数说明。
4.函数内容以冒号起始,并且缩进。
5.return [表达式] 结束函数,选择性的返回一个值给调用方。不带表达式的return相当于返回 None。
其中参数列表和返回值不是必须的,return后也可以不跟返回值,甚至连 return也没有。
对于return后没有返回值的和没有return语句的函数都会返回None值
有些函数可能既不需要传递参数,也没有返回值。没有参数时,包含参数的圆括号也必须写上,圆括号后也必须有“:”。
函数调用
定义一个函数:给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从 Python 命令提示符执行。
函数参数
- 不传参函数
- 参数函数
- 顺序
函数参数种类
形参和实参
- 形参
- 只有在调用时才分配内存单元格。调用结束后,即释放所分配的单元格。因此,形参只在内部有效,函数调用结束返回主调用函数后则不能再使用该形参变量。
- 实参
- 实参是一个确定的值,能够传递给形参
默认参数
##hobby="Trip"处
def usr_manage(name,age,job,hobby="Trip"):
print("用户管理系统".center(16, '-'))
print("\tName:\t",name)
print("\tAge:\t", age)
print("\tJob:\t", job)
print("\tHobby:\t", hobby)
print("用户管理系统".center(16, '-'))
usr_manage("Tom",20,"IT","Coding")
usr_manage("Jim",21,"Student") #不传参则使用默认的
-----用户管理系统-----
Name: Tom
Age: 20
Job: IT
Hobby: Coding
-----用户管理系统-----
-----用户管理系统-----
Name: Jim
Age: 21
Job: Student
Hobby: Trip
-----用户管理系统-----
关键字参数
默认参数,关键字参数,必须放置在位置参数之后
def usr_manage(name,age,job="IT",hobby="Trip"):
print("用户管理系统".center(16, '-'))
print("\tName:\t",name)
print("\tAge:\t", age)
print("\tJob:\t", job)
print("\tHobby:\t", hobby)
print("用户管理系统".center(16, '-'))
##下方处
usr_manage("Tom",20,hobby="Coding",job="Student")
-----用户管理系统-----
Name: Tom
Age: 20
Job: Student
Hobby: Coding
-----用户管理系统-----
不定参数
在python中不定参数主要指*args(以元组形式)和**kwargs(以字典形式)两个魔法变量。
他们俩主要是用于函数定义,我们可以将不定数量的参数传递给一个函数。
def uncertain_para(para,para2,*args):
print("普通位置参数:",para,para2)
print("不定参数:",args)
print(type(args))
uncertain_para(1,2,3,4,'a','b')
uncertain_para([1,2,3],'ab','cd','ef')
普通位置参数: 1 2
不定参数: (3, 4, ‘a’, ‘b’)
<class ‘tuple’>
普通位置参数: [1, 2, 3] ab
不定参数: (‘cd’, ‘ef’)
<class ‘tuple’>
def un_para_key(x,*y,**z):
print(x,y)
print(z)
un_para_key(1,2,'a',a=1,b=2)
1 (2, ‘a’)
{‘a’: 1, ‘b’: 2}
函数属性
函数是Python中另一个使用了句点属性标识并拥有名字空间的领域。
def foo():
'foo() --- Properly created doc string.'
def bar():
pass
bar._doc_ = "Oops, forget the doc str above"
bar.version = 0.1
内嵌函数
–> 作用域
bar()整个函数都处于外部fool()函数的作用域里(fool()是我们可以从外部访问的一个对象区域)。除了在fool()内部,其他地方无法对bar()进行调用。
变量作用域
作用域的产生
当变量在module,Class函数中定义的时候,才会有作用域的概念。
def foo():
a = "foo"
print(a)
foo()
print(a)
NameError: name ‘a’ is not defined
作用域中的变量一般只在作用域内有效。需要注意的是,在if-elif-else,for - else,while-else,try -except(else-finally)等关键字的语句块中不会产生作用域。
作用域的类型:
使用一个变量时,并不需要预先声明他,但真正使用时他必须被绑定到某个内存对象(被定义,赋值)。这种变量名的绑定将在当前作用域引入新变量时,屏蔽外层同名变量。
-
局部作用域(locale – L)
包含在def关键字定义的语句块中,即在函数中定义的变量。每当函数被调用时都会创建一个新的局部作用域。Python中也有递归,即自己调用自己,每次调用都会创建一个新的局部命名空间。在函数内部的变量声明,除非特别的声明为全局变量,否则均默认为局部变量。有些情况需要在函数内部定义全局变量,这时可以使用global关键字来声明变量的作用域为全局。局部变量域就像一个 栈,仅仅是暂时的存在,依赖创建该局部作用域的函数是否处于活动的状态。所以,一般建议尽量少定义全局变量,因为全局变量在模块文件运行的过程中会一直存在,占用内存空间。
注意:如果需要在函数内部对全局变量赋值,需要在函数内部通过global语句声明该变量为全局变量。 -
嵌套作用域(enclosing – E)
-
E也包含在def关键字中,E和L是相对的,E相对于跟上层的函数而言,L是定义在此函数内部的局部作用域。
-
主要为了实现Python的闭包而增加的实现。
-
-
全局作用域(Global – G)
即在模块层次中定义的变量。模块顶层声明的变量具有全局作用域。从外部来看,模块全局变量是一个模块对象的属性。
-
内置作用域(bulit-in – B)
- 系统固定模块中定义的变量
a=100
def boo():
print(a) #在boo()中发现了a的存在,不会调用全局变量,但是程序运行下来,此处找不到a,所以报错
a=10
print(a)
print(boo())
递归函数
在一个函数体的内部,调用函数本身,就被称为递归函数。
匿名函数
python 使用 lambda 来创建匿名函数。
所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
-
lambda 只是一个表达式,函数体比 def 简单很多。
-
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
-
lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
-
虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
格式:
lambda para1,para2, ... paraN : expression using paras
sum = lambda arg1, arg2: arg1 + arg2
# 调用sum函数
print("相加后的值为 : ", sum(10, 20))
print("相加后的值为 : ", sum(20, 20))
相加后的值为 : 30
相加后的值为 : 40
高阶函数
高阶函数:把一个函数名,以实参的形式,传递给这个函数的形参,这个函数就成为高阶函数,
def pow(x):
return x**2
def add(a,b,func):
return func(a)+func(b)
a_value = add(-9,1,pow)
print(a_value)
82
filter函数
f1 = fliter(lambda sr: not sr.endwish("ty"),li)
print(list(f1))
功能:
- 过滤掉序列中不符合函数条件的元素。当序列中需要保留的元素可以用某些函数描述时,就应该想到filter函数。
调用格式:
-
filter(function, sequence)
-
function --> 可以是自定义的函数, 也可以是匿名函数
-
sequence --> 列表,元组, 字符串
-
map 映射
功能:
- 求一个序列或者多个序列进行函数映射后的值。(用list强转)
格式:
-
map(function, iterable1,iterable2)
-
function 的参数可以不止一个
-
iterable1, iterrable2 是传入的参数
-
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(x,y):
return x*y+2
res = map(f,x,y)
print(list(res))
[4, 8, 14, 22, 32]
reduce函数
-
reduce() 函数将一个数据集合(列表,元组等)中的所有数据进行下列操作:
- 用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作;
- 得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
- python3中,它在functools模块中:
from functools import reduce
-
格式:
-
reduce(function, iterable, [initial]) ------reduce(函数,参数,初值)
- functon必须传入两个参数
- iterable:可迭代对象
- initializer :可设初始参数
-
-
例子:
from functools import reduce t = [1,2] # reduce(函数,序列,初始值) # 有初始值会把它加到序列第一个,然后运算 z = reduce(lambda x,y:x*2+y, t, 4) # t2 = [4,1,2,3] print(z) # (4*2+1)*2+1 = 20
apply函数
功能
- pandas中, 应用对象是pandas中的DataFrame或者Series
- 直接对DataFrame或者Series应用函数
- 对pandas中groupby之后的聚合对象应用apply
#apply
import numpy as np
import pandas as pd
a = np.random.randint(low = 0, high = 4, size=(2,4))
print(a)
data = pd.DataFrame(a)
print(data)
[[1 0 1 2]
[1 3 1 2]]
0 1 2 3
0 1 0 1 2
1 1 3 1 2
zip函数
功能:
- 将可迭代对象作为参数,将对象中对应的元素打包成一个个元组,返回由这些元组构成的对象
- 长度不一样时,以长度短的为准
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b) # 打包为元组的列表
[(1, 4), (2, 5), (3, 6)]
>>> zip(a,c) # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]
>>> zip(*zipped) # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
[(1, 2, 3), (4, 5, 6)]