Python函数总结

一、函数的基本用法

1、概念:

函数是对程序逻辑进行结构化或是过程化的一种编程方法,其是组织好的,可重复使用的,用来实现单一,或者相同功能的代码段。

函数提高了应用点的模块性和代码的重复利用率

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

本质:函数是对功能的封装

形式参数:简称形参,本质是一个没有值的变量 实际参数:简称实参,本质是常量,变量或者表达式 传参:实参给形参赋值的过程

而实参的类型取决于形参的需要

2、函数定义:
  def  函数名(参数1,参数2,参数3.。。。):
函数体
return 返回值

注:a、函数命名遵循标识符规则,做到见名知意,小驼峰命名法、

b、参数1,参数2,参数3.....形式参数,不同的参数之间使用逗号隔开,参数的数量没有限制,依据具体的需求决定参数的数量

c、函数体:被封装的功能

d、return:结束函数,将返回值返回给调用者,也可单独使用

e、返回值可为常量、变量、表达式

3、返回值

返回值:表示一个函数执行完毕之后得到的结果

注:对于return语句不带参数,则返回一个None

4、调用

函数的调用:实质就是函数入栈出栈的过程

即:函数的入栈:函数被调用;函数的出栈:函数被调用完毕

注:在函数调用的过程要注意避免出现死循环

5、变量的作用域

变量的作用域:指变量可以被访问的范围

作用域的划分:

L:(local)局部作用域

E:(Enclosing)函数作用域(闭包)

G:(Global)全局作用域

B:(Built-in)内置作用域

变量的查找规则(变量重名):

python中变量的作用域由大到小,依次为内建(built_in B) >全局(glbal G)> 函数的闭包外(enclosing E)> 局部(local L)

注:在变量重名情况下在函数内部访问变量时使用就近原则。

如果将全局变量的名字声明在一个函数体内的时候,全局变量的名字能被局部变量给覆盖掉,此时我们就需要使用global或者nonlocal来声明变量了。

  #1.变量不重名
num1 = 10    #全局作用域

def outer():
num2 = 20    #函数作用域
def inner():
    num3 = 30  #局部作用域
  print(num1,num2,num3)
return inner

f = outer()
f()
  # global:全局的
# 全局变量
num1 = 4
def func1():
  # 声明num1是全局变量的num1
  global  num1
  print(num1)   #4

num1 = 20
func1()

a = 10
def test():
global  a
a = a + 1
print(a)   #UnboundLocalError: local variable 'a' referenced before assignment
   
test()


# nonlocal:不是局部的
# nonlocal;前提条件:必须使用在闭包中
x = 0  # 全局作用域
def outer():
  x = 1       # 函数作用域
   def inner():
      # 将一个局部作用域的变量声明为不是局部的,局部----》函数
    nonlocal x
    x = 2   #局部作用域
    print("inner:",x)
       
#在外部函数中调用内部函数
nner()
print("outer:",x)
outer()
print("global:",x)

 

6、参数

1、参数的传递:

参数的传递有值传递和引用传递

值传递:传递不可变类型的数据,例:num、string、tuple等;在值传递时,形参的改变并不会影响实参

引用传递:传递可变类型的数据,例:list、dict、set等;形参的改变会影响实参的使用

在函数中参数传递的是对象的引用

  #引用传递:传递列表或者字典时,如果改变引用的值,就修改了原始的对象
def check(l):
print(l)
print(id(l))
l.append([1, 23, 2, 3, 4])
return l
   
l = [1, 2, 3, 4]
print(check(l))
print(id(l))

'''
[1, 2, 3, 4]
2902500909320
[1, 2, 3, 4, [1, 23, 2, 3, 4]]
2902500909320
'''
#值传递:当传递不可变对象时,如果改变引用变量的值,只是创建了不同的对象,原始对象并没有改变。

def check(s):
print(s)
print(id(s))
s = "i am test"
print(id(s))
return s

s = "This is a test"
print(check(s))
print(s)

'''
This is a test
2418424029424
2418424029488
i am test
This is a test

2、参数的类型:

a、必须参数:必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

  def printme( str ):
  "打印任何传入的字符串"
  print str
return

#调用printme函数
printme()

b、关键字参数:允许实参的顺序和形参的顺序不一致,因为Python解释器会根据关键字参数的名称自动的匹配

  def show2(name,age):
print("name:%s age:%d" % (name,age))

show2(name="jack",age=47)
# 注:关键字参数使用在实参列表中,不要求顺序保持一致
show2(age=36,name="fadj")
# 注:在实参列表中,可以不全部设置为关键字参数
show2("zhangsan",age=15)

# 注:关键字参数只能出现在实参列表的后面
def show3(a,b,c):
print(a,b,c)

show3(1,4,4)
show3(a=3,c=5,b=5)
show3(45,b=9,c=18)
#show3(a=45,9,18) #SyntaxError: positional argument follows keyword argument

c、默认参数:调用函数的时候,如果没有传递参数,则使用默认值【default】

  #注意1:默认参数体现在形参列表中
def func3(name="abc",age=18):
print("name:%s age:%d" % (name, age))
#注意2:使用了默认参数,则可以选择不传参,使用的默认值,如果传参,则相当于给形参重新赋值
func3()
func3("jack",19)
#注意3:关键字参数和默认参数可以结合使用
func3(name="jack",age=19)
func3("jack",age=19)

#注意4:形参列表可以不全部设置为默认参数,只要吃部分设置,则默认参数出现在形参列表的后面
#报错:SyntaxError: non-default argument follows default argument
# def show4(name="abc",age):
#     print("name:%s age:%d" % (name, age))
# show4("bob",18)

print("hello")

d、不定长参数:可以处理比声明时更多的参数

  #a.*,一般写法为*args
def text1(*num):
print(num)
for n in num:
    print(n)
       
# *不定长参数被当做元组处理,num形参名其实就是元组名
text1(10)
text1(10,4,54,65,65,7)
# 可以传一个元组,但是,元组被当做一个整体全部传参
text1((54,4,64))

# 一般情况下,将不定长参数设置在形参列表的最后
def text2(*num3,num1,num2):
print(num1,num2,num3)

# 如果不定长参数出现在形参列表的前面或者中间,则可以借助于关键字参数传参
#text2(12,43,43)
text2(12,34,num1=35,num2=59)

# 在形参列表,不定长参数最好只出现一个
#错误演示
# def text3(*num3,num2,*num1):
#     print(num1,num2,num3)
# text3(43,53,num2=10,5,5,4)


#b.**,一般写法为**kwargs
def text4(**num3):
print(num3)

#注意1:**,被当做字典处理,传参的时候,需要以key=value的方式进行传参
text4(x=26,y=17)

#注意2:在形参列表中使用**,保证出现在后面

"""
使用场景:单例设计模式
def text(*args,**kwargs):

总结:
a.必需参数使用最多,其次是不定长参数
b.关键字参数和默认参数最多使用在系统函数中
"""
7、匿名函数

lambda表达式:python中的匿名函数主要用来处理一些简单逻辑表达式的封装,使用lambda关键字

优点:不占用内存,提高代码的运行速度

一般格式为:

var = lambda args:表达式

例如:

f = lambda x,y:x+y
#该函数的调用结果为 冒号后的表达式所表达的结果
print(f(1,2))

二、函数进阶

1、概念【特殊用法】:

1、变量可以指向函数

x = abs(-35)
print(x)   # 35

# 一个普通的变量可以指向一个函数,该变量就可以被当做函数调用
f = abs
print(f)
print(f(-100))

def check():
 	print("check")

check()
f1 = check
f1()

2、函数也可以作为变量名

# 本质:函数名就是一个指向函数的变量
print(abs(-28))
# abs = "hello"
# print(abs(-7))

3、函数作为参数使用

# 调用形参中的函数,必须和原函数保持一致【注意是否需要传递参数】
def test(a,b,fun):
 	return fun(a) + fun(b)   #abs(43) + abs(-27)
print(test(43,-27,abs))  #fun = abs

def test1(s1,s2,func):
 	return func(s1) + func(s2)
print(test1("hello","gajghj",len))
2、闭包:

在函数内部定义了另一个函数,即存在外部函数和内部函数

闭包【closure】:在外部函数中定义一个内部函数,并且外部函数的返回值是内部函数的引用。

# 普通函数
def show():
    print("1111")
 	return  num1

# 闭包
def outter():
 	def inner():
     	print("inner")
 	return inner

f = outter()   #f = inner
f()

# 在闭包设置参数,a和b两个变量被称为自由变量【临时变量】
# 闭包的优点:在外部函数中定义的变量,在内部函数可以直接访问
def outer1(a):
 	b = 10
	def inner1():
     	print(a + b)
	return inner1

f1 = outer1(23)  #f1 = inner1
f1()


# 内部函数设置参数
def outer2(a):
 	b = 10
 	def inner2(c):
     	print(a + b + c)
	return inner2

f2 = outer2(23)
f2(12)

 

3、装饰器:

装饰器【Decorator】:使其他函数在不需要做任何代码的变动下,为函数添加功能,装饰器的返回值也是一个函数。

本质:装饰器的本质就是一个闭包,其作用是将一个函数作为参数,返回另一个函数

装饰器函数运行在函数定义的时候

装饰器需要返回一个可执行的对象

装饰器返回的可执行对象要兼容函数f的参数

import  time
#1.简单的装饰器
def test():
 	print("hello")
# func就是需要被装饰的函数
def outer(func):
 	def inner():
     	# 增加新功能
    	print("new~~~~")
     	# 调用原函数
    	func()
 	return  inner

f1 = outer(test)
f1()

# 练习:书写装饰器,计算test函数执行的时间
def outer(func):
 	def inner():
     	t1 = time.time()
        func()
		t2 = time.time()
		print(t2 - t1)
	return  inner
f1 = outer(test)
f1()

#2.带有参数的装饰器
def getAge(age):
 	print(age)
# getAge(10)
# getAge(-36)
# 注意:被装饰的函数有参数,inner不一定需要设置参数,只有当需要在inner内部对参数进行操作的时候,则需要同步
def wrapper1(func):
 	def inner(a):
     #数据的校验
     	if a < 0:
         	a = -a
        func(a)
 	return  inner

f = wrapper1(getAge)
f(10)
f(-36)


# 使用装饰器语法糖
# 注意:使用@,必须保证装饰器存在的情况下,才能给函数增加功能
def wrapper2(func):
 	def inner(a):
     	# 数据的校验
     	if a < 0:
         	a = -a
		 func(a)
	return inner

@wrapper2
def getAge1(age):
 	print(age)
    
getAge1(-19)

# 参数为不定长参数的装饰器
# 使用场景:一个装饰器可以同时作用于多个不同函数的情况
def wrapper3(func):
 	def inner(*args,**kwargs):
     	# 新增的功能
     	print("abc")
     #调用原函数
     	func(*args,**kwargs)
 	return  inner

@wrapper3
def test(a,b):
     print(a,b)

test(10,20)

@wrapper3
def test1():
 print("gsjrg")

test1()

# 多个装饰器作用于同一个函数
def wrapper11(func):
 	def inner(*args,**kwargs):
     	# 新增的功能
     	print("装饰器~~~~11")
     	# 调用原函数
     	func(*args,**kwargs)
 	return  inner

def wrapper22(func):
 	def inner(*args,**kwargs):
     	# 新增的功能
     	print("装饰器~~~~22")
     	# 调用原函数
     	func(*args,**kwargs)
 	return  inner

@wrapper11    # func:check
@wrapper22      # func:被wrapper11装饰之后的函数
def check():
 	print("check")

check()
#总结:多个装饰器作用于同一个函数的时候,从上往下依次执行,但是,原函数只被调用一次
4、偏函数

通过设定默认参数,可以降低调用的难度,偏函数也可以起到这样的作用

概念:对函数的参数做一些控制的函数

注意:偏函数一般不需要自己定义,直接使用【functools模块其中提供了偏函数的使用】

import  functools


print(int("23534"))
# print(int("abc345"))  #ValueError: invalid literal for int() with base 10: 'abc345'

# 在int中有一个默认参数base,用来指明当前数据的进制
print(int("110"))
print(int("110",base=10))
print(int("1010",base=2))
print(int("1010",2))
# 自定义一个函数,设置一个默认参数base,默认值设置为2
def int2(x,base=2):
 	return int(x,base)

print(int2("1010"))
print(int2("1010",10))

# 系统的functools模块中提供了偏函数的实现
# 参数:已经存在的函数名   默认参数
int3 = functools.partial(int,base=2)
print(int3("1110"))
print(int3("1110",base=10))

# 思想:根据一个已经存在的函数,通过修改该函数参数的默认值,生成一个新的函数,被称为偏函数

三、高阶函数

1、filter():过滤

"""
filter(function,iterable)  通过一定的条件过滤可迭代对象中的元素

工作原理:把传入的函数依次作用于可迭代对象的每一个元素,根据返回的布尔值【True或者False】决定是否保留元素
如果返回True,则表示需要保留该元素;如果返回False,则表示需要过滤掉该元素
"""
# 将列表中的偶数筛选出来
list1 = [1,2,3,4,5,6,7,8]
# 自定义【追加】
newList1 = []
for num in list1:
 	if num % 2 == 0:
    	 newList1.append(num)
print(newList1)
# 自定义【删除】
newList2 = list1.copy()
for num in newList2:
  	if num % 2 == 1:
     	newList2.remove(num)
print(newList2)

#方式三:列表生成式
newList3 = [num for num in list1 if num % 2 == 0]
print(newList3)

# filter
def func(num):
	# 保留偶数元素
 	if num % 2 == 0:
     	return True
	# 过滤奇数元素
 	return False

newList4 = list(filter(func,list1))
print(newList4)

# 将爱好为"无"的数据剔除掉
data = [['姓名', '爱好', '年龄'],['tom', '无', 10],['jack', '唱歌', 28]]
def func2(s):
 	if s == "无":
     	return False
	 return  True
for line in data:
  	result = list(filter(func2,line))
  	print(result)

2、map():映射

"""
map(function,Iterable)  会根据的函数对指定的序列做出映射
function:函数
iterable:可迭代对象,序列
工作原理:函数会以序列中的每一个元素作为参数,返回包含函数的功能的新列表
功能:将传入的函数依次作用于序列中的每一个元素,并把结果作为新的iterable返回
"""
# 计算列表中各个元素的平方
list1 = [1,2,3,4,5]
# 自定义
newList1 = []
for num in list1:
 	newList1.append(num ** 2)
print(newList1)

# 列表生成式
newList2 = [num ** 2 for num in list1]
print(newList2)

# 生成器
newList3 = list((num ** 2 for num in list1))
print(newList3)

# map[def定义的函数]
def func(x):
  return  x ** 2

result = map(func,list1)
print(result)
print(type(result))
newList4 = list(result)
print(newList4)

"""
传给map的函数的要求:
 a.参数只能有一个【默认将可迭代对象的一个元素传递给该函数】
 b.该函数必须有返回值,否则得到的可迭代对象中的元素为None
"""
#方式五:map[匿名函数]
newList5 = list(map(lambda x:x ** 2,list1))
print(newList5)

# 已知有一个整数列表,将转换为字符串列表
#例如:[2,3,4,5]------>['2','3','4','5']   str()
list2 = [2,3,4,5]
newL1 = []
for num in list2:
 	newL1.append(str(num))
print(newL1)
newL2 = [str(num) for num in list2]
newL3 = list((str(num) for num in list2))
newL4 = list(map(str,list2))
print(newL4)

reduce():迭代【累积】

from functools import reduce
"""
导入模块:functools
reduce(function,iterable):函数会对序列中的元素进行累积
功能:用传给reduce的函数先序列中的第1,2个元素进行操作,
用得到的结果和第3个元素进行操作,用得到的结果和第4个元素进行操作。。。。

举例:
f,[a,b,c,d]
reduce(f,[a,b,c,d])
工作原理:f(f(f(a,b),c),d),类似于递归
"""

# 计算一个整数列表中元素的和
# 一:自定义
list1 = [1,2,3,4,5]
total = 0
for num in list1:
 	total += num
print(total)

# 二:reduce【def定义函数】
def mySum(x,y):
 return x + y
result0 = reduce(mySum,list1)
print(result0)
"""
mySum(1,2)---->3
mySum(3,3)---->6
mySum(6,4)---->10
mySum(10,5)---->15
"""

# 三:reduce[匿名函数]
result1 = reduce(lambda x,y:x + y,list1)
print(result1)
"""
函数的注意事项:
 a.必须有两个参数
 b.必须设置返回值【报错:TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'】
"""

# 将[1,3,5,7,9]转换为整数13579
list2 = [1,3,5,7,9]
def func(x,y):
 	return  x * 10 + y

result3 = reduce(func,list2)
print(result3)

# 自定义一个函数,实现str转换为int的函数  int(xx)
def charToNum(s):
 # 自定义字符串和整型之间的映射关系
 	digits = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6}
  return digits[s]

# 需求:“24356”------》24356
# a.产生映射关系
r0 = list(map(charToNum,"24356"))
print(r0)
#b.使用reduce累积
r1 = reduce(func,r0)
print(r1)
print(type(r1))

r2 = reduce(func,map(charToNum,"23456"))
print(r2)

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄