Python函数基础到进阶分享一:函数参数,序列解包,变量作用域

本文深入探讨了Python函数的参数类型,包括普通参数、默认参数、可变参数、关键字参数和命名参数。通过实例展示了如何使用序列解包、变量作用域以及LEGB规则。内容涵盖函数定义、参数传递、默认参数陷阱以及如何避免问题。同时讨论了不同参数类型的混合使用,强调了良好的编程实践。
摘要由CSDN通过智能技术生成

python函数参数有哪些?序列解包?变量作用域以及访问顺序?你真的知道?已经整理好,一起来复习复习吧

https://mp.weixin.qq.com/s/HQXh03uLuVC5MRzYFsM4uA

python函数参数:位置参数,可变参数,关键字参数,命名参数,序列解包?变量作用域以及访问顺序?你明白(记得吗)吗?已经整理好,一起来看看(复习复习)吧…

引言:

谚语有云:“不积跬步,无以至千里;不积小流,无以成江海。”

大佬的牛逼,往往来自朴实无华的基础,越简单越实用。

菜鸟程序员,调用函数,一行一行写代码

牛皮程序员,自定义函数,一块一块写代码

大神程序员,封装类模块,一篇一篇写代码

今天,让我们一起,积累函数基础,从 面向过程 向 面向对象 编程出发:

1、函数

函数的概念 ●●

函数:是组织好的,可重复使用的,用来实现单一,或者相关联功能的代码段;函数能提高应用的模块性,和代码的重复使用率。

说白了,有个功能你要重复实现,多次写你嫌麻烦,就把他编写成函数,达到一次编写,多次使用的效果。

比如:你想计算数列的和,如果不用已有的sum()函数,一般你都可能都是这样:

计算1+2+3+···+1000

计算1+3+5+···+11+···

计算2+4+6+···+10+···

函数

def sum_func(lst):
s=0
for i in range(len(lst)):
s=s+lst[i]
return s

传递参数,调用函数

sum_func([1,2,3,4,5])
15
sum_func([10,4,6,90,100])
210

这个函数定义好了,你下次要计算某数列的和,只要调用函数,传入参数即可,不用每次写一堆。

这这是个简单的例子,Python本身有很多函数可以调用,也可以自定义函数,实现个性化需求,那如何定义一个函数呢?

自定义函数

规则:

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

注释

函数体

1、函数代码块以 def 关键词开头,后接函数名和圆括号

def hello():

“”“该函数输出 hello”“”

print(‘hello world’)

2、任何传入的参数和自变量必须放在圆括号当中。

3、函数体的第一行一般可用来存放对该函数的解释性信息。,严格缩进。

4、函数必须以冒号结尾

5、括号内的参数为形参,调用时候传递的参数为实参。

说明:(自定义斐波拉契数列函数)

2函数的参数

在python中,函数的参数有很多种:普通参数或者位置参数,默认参数、可变参数、关键字参数、重命名关键字参数。下面一一说明:

普通参数

普通参数或者位置参数:

以正确的顺序传入函数。调用时的数量必需和声明时的保持一致,如果改变顺序,需要指明形参代表的正确实参。

def people(name,gender):
print(“name:”,name)
print(“gender:”,gender)

people(“jack”,“男”)#按顺序传入参数
name: jack
gender: 男

people(“男”,“jack”) #不按顺序传入,发生错位
name: 男
gender: jack

people(gender=“男”,name=“jack”) #按照参数名传入,可以不考虑参数顺序
name: jack
gender: 男

people(“jack”,“男”,“US”) #没有定义形参,传入实参时发生错误

TypeError Traceback (most recent call last)
in
----> 1 people(“jack”,“男”,“US”)

TypeError: people() takes 2 positional arguments but 3 were given

默认参数

默认参数调用的时候,可以给他赋值可以不赋值,简化了函数调用,具有很大的灵活性。

注意:

1、默认参数只能在餐胡列表的最右端,任何一个默认参数右边不能有非默认参数。

2、默认参数必须是不变对象,如果可变可能掉坑里。

默认参数

def people(name,gender,city=“China”):
print(“name:”,name)
print(“gender:”,gender)
print(“city:”,city)
#默认参数city=“China”,传入实参时,忽略默认参数,也会正常赋值并体现
people(“jack”,“男”)
name: jack
gender: 男
city: China

people(“jack”,“男”,city=“b”)#默认参数,可以改变定义时候的值,赋于新值
name: jack
gender: 男
city: b
默认参数虽好,可不要“贪杯哦”,小心掉坑里!!!

默认参数必须指定不可变对象

def demo(item,l=[]):
l.append(item)
return l

函数功能:给一个列表,末尾追加“end”,测试两次,貌似没问题

demo(“end”,[1,2,3])
[1, 2, 3, ‘end’]
demo(“end002”,[1,2,3])
[1, 2, 3, ‘end002’]

demo(“end003”) #咦~,和想的不一样??
[‘end003’]
demo(“end004”)
[‘end003’, ‘end004’] #不应该是[‘end004’]吗?

掉坑里了,原因是默认参数必须指定不可变对象

重新定义:

def demo(item,l=None):
if l is None:
l=[]

new_l=l[:]    
new_l.append(item)
return new_l

#调用demo
print(demo(“end”,[1,2,3]))
print(demo(“end002”,[1,2,3]))
print(demo(“end003”))
print(demo(“end004”))

out:
[1, 2, 3, ‘end’]
[1, 2, 3, ‘end002’]
[‘end003’]
[‘end004’]

可变参数 *args

1、可变参数就是传入的参数个数可变,可以是1个,2个,任意个,还可以是0个。

2、可变参数在参数前面加1个*,接收的是一个tuple类型。

3、可变参数可以直接传入,如func(1,2,3),这时候不加*;可以组装成list或者tuple,再通过args传入,如:func((1,2,3))

例:给定a,b,c···,计算a2+b2+c^2+···
def csum(*number):
sum=0
for i in number:
sum=sum+i**2
return sum

csum(1,2,3,4) #返回 30

如果已经是一个列表或者元祖,在前面加*表示将序列解包

num=[1,2,3]
print(csum(*num)) # 返回 14

num2=(3,4,5)
print(csum(*num2)) # 返回 50

num={1:“a”,2:“b”,3:“c”}
print(csum(*num.keys())) # 返回 14

print(csum(*num.values())) #字符不能运算

序列解包和位置参数一起使用

csum(1,*(2,3),4) # 返回 30

关键字参数 **kw

可变参数在函数调用的时候,自动组装成一个tuple;

而关键字参数在调用的时候,这些关键字在函数内部自动组装成一个dict。

关键字参数的作用是:扩展函数的功能。如果除了必填项,选填项可以用关键字参数来自动补充

#定义关键字参数**kw,“kw”可以是你喜欢的任何名字(kkww,keyword…),但是习惯于kw
def people(name,gender,**kw):
print(“name:”,name)
print(“gender:”,gender)
print(“other:”,kw)

people(“jack”,“M”,age=45) #age=45,返回字典{‘age’: 45}

out:
name: jack
gender: M
other: {‘age’: 45}

people(“jack”,“M”,age=45,city=“shanghai”)

out:
name: jack
gender: M
other: {‘age’: 45, ‘city’: ‘shanghai’}

上面复杂的写法可以简化

other={‘age’: 45, ‘city’: ‘shanghai’}
people(“jack”,“M”,**other)

out:
name: jack
gender: M
other: {‘age’: 45, ‘city’: ‘shanghai’}

命名关键字参数

命名关键字参数,以*分割,后面的是命名参数,

如果有可变参数agers,则不需要分割

如果没有*分割,后面的被认为是位置参数

命名关键字参数,以分割,后面的是命名参数,如果有可变参数agers,则不需要*分割

#001 一个分割,后面的是命名参数
def people1(name,age,
,city,job): #一个*分割
print(name,age,city,job)

people1(“jack”,24,city=“beijing”,job=“doctor”) #调用people1,返回jack 24 beijing doctor

#002 有可变参数arg,后的是命名参数,这时候不需要分割
def people2(name,age,*arg,city,job): # *arg 后的是命名关键字参数
print(name,age,city,job)

people2(“jack”,24,city=“beijing”,job=“doctor”) #people2 返回jack 24 beijing doctor

#003 *arg 是规范写法,*arg可以命名为任意你喜欢,你开心的词
def people3(name,age,*ttt,city=“beijing”,job):
print(name,age,city,job)

people3(“jack”,24,job=“doctor”) #people3 返回jack 24 beijing doctor
混合使用各种参数

各种参数的混合使用(可以用,但是不建议)

def f1(a,b,c=0,*kk,**mm):
print(“a={0},\nb={1},\nc={2},\nargs={3},\nkw={4}”.format(a,b,c,kk,mm))

f1(1,2) # 调用

out:
a=1,
b=2,
c=0,
args=(),
kw={}

f1(1,2,7,“a”,“b”,x=99,y=10) # 传入参数,调用函数

out:
a=1,
b=2,
c=7,
args=(‘a’, ‘b’),
kw={‘x’: 99, ‘y’: 10}

args=[1,2,3,4]
kw={“abc”:“123”,“qwe”:“345”}
f1(11,22,*args,**kw) # 传入参数,调用函数

out:
a=11,
b=22,
c=1,
args=(2, 3, 4),
kw={‘abc’: ‘123’, ‘qwe’: ‘345’}

作业:
稍微改改下面函数,实现多数相乘
def proc(x,y):
return x*y

思路:可变参数。

3函数变量的作用域

变量的作用域

1、变量的作用域:变量起作用的范围。

2、局部变量:在函数内部定义的普通变量只在函数内部起作用,函数结束后,局部变量自动删除。

3、全局变量:通过关键词global来定义:

a、一个变量已经在函数外定义,如果在函数内需要为这个变量赋值,并要将这个赋值结果反映到函数外,可以在函数内使用global将其声明为全局变量。

b、如果一个变量在含糊外没有设定,在函数内部也可以直接将一个变量定义为全局变量,该函数执行后,将增加一个新的全局变量。

4、除了全局变量和局部变量,Python还支持使用nonlocal关键字定义一种介于二者之间的变量。nonlocal声明的变量会引用距离最近的非全局作用域变量,要求声明的变量已经存在,关键字nonlocal不会创建形变量。

def demo():
global x #声明全局变量x
x=3
y=4
print(x,y)

demo() #调用 返回3 4

x #查看x的值,返回3,

y #查看y的值,因为y在函数内定义y=4,外部并没有定义,所以报错:y没定义。

NameError Traceback (most recent call last)
in
----> 1 y

NameError: name ‘y’ is not defined

各变量访问的LEGB顺序:Local==>Enclosing==>Global==>Builtin

变量访问的LEGB顺序:Local==>Enclosing==>Global==>Builtin

x=3
def outer():
y=5
#这个自定义函数和内置函数名字相同,会在当前作用域和更内层作用域中影响内置函数map()的正常使用
def map():
return “我是一个假的map函数”

def inner():
    x=7
    y=9
    #最内层的作用域,局部变量x,y被优先访问
    #局部作用域,闭包作用域内都不存在函数max,最后的内置作用域(builtin)内搜索到max函数
    #当前作用域中不存在map,但在外部的闭包作用域内搜索到,并没有调用内置函数map
    print("inner:",x,y,max(x,y),map())

inner()
#在当前的作用域(闭包、enclosing)内,y可以直接访问
#当前作用域不存在x,继续到全局作用域(global)去搜索
#当前作用域中不存在max,外层全局作用域也不存在,最后再内置作用域(builtin)内搜索到max
#当前作用域中有个map,直接调用了,并没有调用内置函数map
print("outer:",x,y,max(x,y),map())

outer()
#当前作用域中有x=3,可以直接访问,但不存在y
#优于当前作用域处于全局作用域,按照python变量搜索的顺序,会继续在内置作用域搜索
#不会去搜索enclosing和local作用域,但在内置作用域也不存在y,代码引发异常
print(“outside:”,x,y,max(x,y))


out:
inner: 7 9 9 我是一个假的map函数
outer: 3 5 5 我是一个假的map函数

NameError Traceback (most recent call last)
in
21 print(“outer:”,x,y,max(x,y),map())
22 outer()
—> 23 print(“outside:”,x,y,max(x,y))
24

NameError: name ‘y’ is not defined

参考文献链接:

https://www.liaoxuefeng.com/wiki/1016959663602400/1017261630425888

https://mp.weixin.qq.com/s/GQUhcUkG8PXec53_2zQapA

THEEND

往 期 精 选

1、【Python数据挖掘实战案例】K-Means广告效果聚类分析

2、【Pythons数据挖掘实战案例】用ARIMA时间序列模型预测未来销量

3、【Pythons数据挖掘实战案例】用户流失预测分析

4、Python数据挖掘实战案例:促销前的销售预测

5、Python数据挖掘实战:客户价值识别实现差异化管理

6、【机器学习算法原理推导】最小二乘法求解线性回归手写推导全过程详解

7、【机器学习算法原理推导】梯度下降法求解线性回归手写推导全过程详解

8、【机器学习算法原理推导】Logistic回归手写推导全过程详解

9、基于SAS的金融风控应用——评分卡模型开发流程

原文链接:
https://mp.weixin.qq.com/s/HQXh03uLuVC5MRzYFsM4uA

觉得学到了,记得转发、收藏、在看支持一下

你的点点支持,是我更新的动力。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值