找做企业网站周口市城乡建设局网站
news/
2025/9/28 1:56:36/
文章来源:
找做企业网站,周口市城乡建设局网站,wordpress 界面优化,wordpress 获取文章分类函数进阶 函数进阶1.参数的补充1.1 参数内存地址相关【面试题】1.2 函数的返回值是内存地址1.3 参数的默认值【面试题】1.4 动态参数 2. 函数和函数名2.1 函数做元素2.2 函数名赋值2.3 函数名做参数和返回值 3.返回值和print4. 作用域4.1 函数为作用域4.2 全局和局部4.3 global… 函数进阶 函数进阶1.参数的补充1.1 参数内存地址相关【面试题】1.2 函数的返回值是内存地址1.3 参数的默认值【面试题】1.4 动态参数 2. 函数和函数名2.1 函数做元素2.2 函数名赋值2.3 函数名做参数和返回值 3.返回值和print4. 作用域4.1 函数为作用域4.2 全局和局部4.3 global关键字 总结 函数进阶 目标掌握函数相关易错点 项目开发必备技能。
今日概要
参数的补充函数名函数名到底是什么返回值和print傻傻分不清楚。函数的作用域
1.参数的补充
在函数基础部分我们掌握函数和参数基础知识掌握这些其实完全就可以进行项目的开发。
今天的补充的内容属于进阶知识包含内存地址相关、面试题相关等在特定情况下也可以让代码更加简洁提升开发效率。
1.1 参数内存地址相关【面试题】
在开始开始讲参数内存地址相关之前我们先来学习一个技能
如果想要查看下某个值的在内存中的地址
v1 武沛齐
addr id(v1)print(addr) # 140691049514160v1 [11,22,33]
v2 [11,22,33]print( id(v1) )
print( id(v2) )v1 [11,22,33]
v2 v1print( id(v1) )
print( id(v2) )记住一句话函数执行传参时传递的是内存地址。 def func(data):print(data, id(data)) # 武沛齐 140247057684592v1 武沛齐
print(id(v1)) # 140247057684592func(v1)
面试题请问Python的参数默认传递的是什么
Python参数的这一特性有两个好处 节省内存 对于可变类型且函数中修改元素的内容所有的地方都会修改。可变类型列表、字典、集合。 # 可变类型 修改内部修改
def func(data):data.append(999)v1 [11,22,33]
func(v1)print(v1) # [11,22,33,666]# 特殊情况可变类型 重新赋值
def func(data):data [武沛齐,alex]v1 [11,22,33]
func(v1)print(v1) # [11,22,33]# 特殊情况不可变类型无法修改内部元素只能重新赋值。
def func(data):data alexv1 武沛齐
func(v1)其他很多编程语言执行函数时默认传参时会将数据重新拷贝一份会浪费内存。
提示注意其他语言也可以通过 ref 等关键字来实现传递内存地址。
当然如果你不想让外部的变量和函数内部参数的变量一致也可以选择将外部值拷贝一份再传给函数。
import copy# 可变类型 修改内部修改
def func(data):data.append(999)v1 [11, 22, 33]
new_v1 copy.deepcopy(v1) # 拷贝一份数据
func(new_v1)print(v1) # [11,22,33]1.2 函数的返回值是内存地址
def func():data [11, 22, 33]return datav1 func()
print(v1) # [11,22,33]上述代码的执行过程
执行func函数data [11, 22, 33] 创建一块内存区域内部存储[11,22,33]data变量指向这块内存地址。return data 返回data指向的内存地址v1接收返回值所以 v1 和 data 都指向 [11,22,33] 的内存地址两个变量指向此内存引用计数器为2由函数执行完毕之后函数内部的变量都会被释放。即删除data变量内存地址的引用计数器-1
所以最终v1指向的函数内部创建的那块内存地址。
def func():data [11, 22, 33]return datav1 func()
print(v1) # [11,22,33]v2 func()
print(v2) # [11,22,33]上述代码的执行过程
执行func函数data [11, 22, 33] 创建一块内存区域内部存储[11,22,33]data变量指向这块内存地址 1000001110。return data 返回data指向的内存地址v1接收返回值所以 v1 和 data 都指向 [11,22,33] 的内存地址两个变量指向此内存引用计数器为2由函数执行完毕之后函数内部的变量都会被释放。即删除data变量内存地址的引用计数器-1
所以最终v1指向的函数内部创建的那块内存地址。(v1指向的1000001110内存地址)
执行func函数data [11, 22, 33] 创建一块内存区域内部存储[11,22,33]data变量指向这块内存地址 11111001110。return data 返回data指向的内存地址v2接收返回值所以 v1 和 data 都指向 [11,22,33] 的内存地址两个变量指向此内存引用计数器为2由函数执行完毕之后函数内部的变量都会被释放。即删除data变量内存地址的引用计数器-1
所以最终v1指向的函数内部创建的那块内存地址。(v1指向的11111001110内存地址)
def func():data [11, 22, 33]print(id(data))return datav1 func()
print(v1, id(v1)) # [11,22,33]v2 func()
print(v2, id(v1)) # [11,22,33]1.3 参数的默认值【面试题】
这个知识点在面试题中出现的概率比较高但真正实际开发中用的比较少。
def func(a1,a218):print(a1,a2)原理Python在创建函数未执行时如果发现函数的参数中有默认值则在函数内部会创建一块区域并维护这个默认值。 执行函数未传值时则让a2指向 函数维护的那个值的地址。 func(root)执行函数传值时则让a2指向新传入的值的地址。 func(admin,20)在特定情况【默认参数的值是可变类型 list/dict/set】 【函数内部会修改这个值】下参数的默认值 有坑 。 坑 # 在函数内存中会维护一块区域存储 [1,2,666,666,666] 100010001
def func(a1,a2[1,2]):a2.append(666)print(a1,a2)# a1100
# a2 - 100010001
func(100) # 100 [1,2,666]# a1200
# a2 - 100010001
func(200) # 200 [1,2,666,666]# a199
# a2 - 1111111101
func(99,[77,88]) # 66 [177,88,666]# a1300
# a2 - 100010001
func(300) # 300 [1,2,666,666,666] 大坑 # 在内部会维护一块区域存储 [1, 2, 10, 20,40 ] ,内存地址 1010101010
def func(a1, a2[1, 2]):a2.append(a1)return a2# a110
# a2 - 1010101010
# v1 - 1010101010
v1 func(10)
print(v1) # [1, 2, 10]# a120
# a2 - 1010101010
# v2 - 1010101010
v2 func(20)
print(v2) # [1, 2, 10, 20 ]# a130
# a2 - 11111111111 [11, 22,30]
# v3 - 11111111111
v3 func(30, [11, 22])
print(v3) # [11, 22,30]# a140
# a2 - 1010101010
# v4 - 1010101010
v4 func(40)
print(v4) # [1, 2, 10, 20,40 ] 深坑 # 内存中创建空间存储 [1, 2, 10, 20, 40] 地址1010101010
def func(a1, a2[1, 2]):a2.append(a1)return a2# a110
# a2 - 1010101010
# v1 - 1010101010
v1 func(10)# a120
# a2 - 1010101010
# v2 - 1010101010
v2 func(20)# a130
# a2 - 11111111111 [11,22,30]
# v3 - 11111111111
v3 func(30, [11, 22])# a140
# a2 - 1010101010
# v4 - 1010101010
v4 func(40)print(v1) # [1, 2, 10, 20, 40]
print(v2) # [1, 2, 10, 20, 40]
print(v3) # [11,22,30]
print(v4) # [1, 2, 10, 20, 40] 1.4 动态参数
动态参数定义函数时在形参位置用 *或** 可以接任意个参数。
def func(*args,**kwargs):print(args,kwargs)func(宝强,杰伦,n1alex,n2eric)在定义函数时可以用 *和**其实在执行函数时也可以用。 形参固定实参用*和** def func(a1,a2):print(a1,a2)func( 11, 22 )
func( a11, a22 )func( *[11,22] )
func( **{a1:11,a2:22} )形参用*和**实参也用 *和** def func(*args,**kwargs):print(args,kwargs)func( 11, 22 )
func( 11, 22, name武沛齐, age18 )# 小坑([11,22,33], {k1:1,k2:2}), {}
func( [11,22,33], {k1:1,k2:2} )# args(11,22,33),kwargs{k1:1,k2:2}
func( *[11,22,33], **{k1:1,k2:2} ) # 值得注意按照这个方式将数据传递给args和kwargs时数据是会重新拷贝一份的可理解为内部循环每个元素并设置到args和kwargs中。所以在使用format字符串格式化时可以可以这样
v1 我是{},年龄{}。.format(武沛齐,18)
v2 我是{name},年龄{age}。.format(name武沛齐,age18)v3 我是{},年龄{}。.format(*[武沛齐,18])
v4 我是{name},年龄{age}。.format(**{name:武沛齐,age:18})2. 函数和函数名
函数名其实就是一个变量这个变量只不过代指的函数而已。
name 武沛齐def add(n1,n2):return n1 n2注意函数必须先定义才能被调用执行解释型语言。
# 正确
def add(n1,n2):return n1 n2ret add(1,2)
print(ret) # 错误
ret add(1,2)
print(ret) def add(n1,n2):return n1 n22.1 函数做元素
既然函数就相当于是一个变量那么在列表等元素中是否可以把行数当做元素呢
def func():return 123data_list [武沛齐, func, func , func() ]print( data_list[0] ) # 字符串武沛齐
print( data_list[1] ) # 字符串 func
print( data_list[2] ) # 函数 func
print( data_list[3] ) # 整数 123res data_list[2]()
print( res ) # 执行函数 func并获取返回值print再输出返回值。print( data_list[2]() ) # 123注意函数同时也可被哈希所以函数名通知也可以当做 集合的元素、字典的键。
掌握这个知识之后对后续的项目开发有很大的帮助例如在项目中遇到根据选择做不同操作时 情景1例如要开发一个类似于微信的功能。 def send_message():发送消息passdef send_image():发送图片passdef send_emoji():发送表情passdef send_file():发送文件passprint(欢迎使用xx系统)
print(请选择1.发送消息2.发送图片3.发送表情4.发送文件)
choice input(输入选择的序号)if choice 1:send_message()
elif choice 2:send_image()
elif choice 3:send_emoji()
elif choice 4:send_file()
else:print(输入错误)def send_message():发送消息passdef send_image():发送图片passdef send_emoji():发送表情passdef send_file():发送文件passdef xxx():收藏passfunction_dict {1: send_message,2: send_image,3: send_emoji,4: send_file,5: xxx
}print(欢迎使用xx系统)
print(请选择1.发送消息2.发送图片3.发送表情4.发送文件)
choice input(输入选择的序号) # 1func function_dict.get(choice)
if not func:print(输入错误)
else:# 执行函数func() 情景2例如某个特定情况要实现发送短信、微信、邮件。 def send_msg():发送短信passdef send_email():发送图片passdef send_wechat():发送微信# 执行函数
send_msg()
send_email()
send_wechat()def send_msg():发送短信passdef send_email():发送图片passdef send_wechat():发送微信passfunc_list [ send_msg, send_email, send_wechat ]
for item in func_list:item()上述两种情景在参数相同时才可用如果参数不一致会出错。所以在项目设计时就要让程序满足这一点如果无法满足也可以通过其他手段时间例如
情景1
def send_message(phone,content):发送消息passdef send_image(img_path, content):发送图片passdef send_emoji(emoji):发送表情passdef send_file(path):发送文件passfunction_dict {1: [ send_message, [15131255089, 你好呀]],2: [ send_image, [xxx/xxx/xx.png, 消息内容]],3: [ send_emoji, []],4: [ send_file, [xx.zip] ]
}print(欢迎使用xx系统)
print(请选择1.发送消息2.发送图片3.发送表情4.发送文件)
choice input(输入选择的序号) # 1item function_dict.get(choice) # [ send_message, [15131255089, 你好呀]],
if not item:print(输入错误)
else:# 执行函数func item[0] # send_messageparam_list item[1] # [15131255089, 你好呀]func(*param_list) # send_message(*[15131255089, 你好呀])情景2
def send_msg(mobile, content):发送短信passdef send_email(to_email, subject, content):发送图片passdef send_wechat(user_id, content):发送微信passfunc_list [{name: send_msg, params: {mobile: 15131255089, content: 你有新短消息}},{name: send_email, params: {to_email: wupeiqilive.com, subject: 报警消息, content: 硬盘容量不够用了}},{name: send_wechat, params: {user_id: 1, content: 约吗}},
]# {name: send_msg, params: {mobile: 15131255089, content: 你有新短消息}},
for item in func_list:func item[name] # send_msgparam_dict item[params] # {mobile: 15131255089, content: 你有新短消息}func(**param_dict) # send_msg(**{mobile: 15131255089, content: 你有新短消息})2.2 函数名赋值 将函数名赋值给其他变量函数名其实就个变量代指某函数如果将函数名赋值给另外一个变量则此变量也会代指该函数例如 def func(a1,a2):print(a1,a2)xxxxx func# 此时xxxxx和func都代指上面的那个函数所以都可以被执行。
func(1,1)
xxxxx(2,2)def func(a1,a2):print(a1,a2)func_list [func,func,func]func(11,22)
func_list[0](11,22)
func_list[1](33,44)
func_list[2](55,66)对函数名重新赋值如果将函数名修改为其他值函数名便不再代指函数例如 def func(a1,a2):print(a1,a2)# 执行func函数
func(11,22)# func重新赋值成一个字符串
func 武沛齐print(func)def func(a1,a2):print(a1a2)func(1,2)def func():print(666)func()注意由于函数名被重新定义之后就会变量新被定义的值所以大家在自定义函数时不要与python内置的函数同名否则会覆盖内置函数的功能例如 id,bin,hex,oct,len...# len内置函数用于计算值得长度
v1 len(武沛齐)
print(v1) # 3# len重新定义成另外一个函数
def len(a1,a2):return a1 a2# 以后执行len函数只能按照重新定义的来使用
v3 len(1,2)
print(v3)2.3 函数名做参数和返回值
函数名其实就一个变量代指某个函数所以他和其他的数据类型一样也可以当做函数的参数和返回值。 参数 def plus(num):return num 100def handler(func):res func(10) # 110msg 执行func并获取到的结果为:{}.format(res)print(msg) # 执行func并获取到的结果为:110# 执行handler函数将plus作为参数传递给handler的形式参数func
handler(plus)返回值 def plus(num):return num 100def handler():print(执行handler函数)return plusresult handler()
data result(20) # 120
print(data)3.返回值和print
对于初学者的同学很多人都对print和返回值分不清楚例如
def add(n1,n2):print(n1 n2)v1 add(1,3)
print(v1)# 输出
4
Nonedef plus(a1,a2):return a1 a2v2 plus(1,2)
print(v2)
# 输出
3这两个函数是完全不同的
在函数中使用print只是用于在某个位置输出内容而已。在函数中使用return是为了将函数的执行结果返回给调用者以便于后续其他操作。
在调用并执行函数时要学会分析函数的执行步骤。
def f1():print(123)def f2(arg):ret arg()return retv1 f2(f1)
print(v1)# 输出
123
Nonedef f1():print(123)def f2(arg):ret arg()return f1v1 f2(f1)v2 v1()
print(v2)# 输出
123
123
None4. 作用域
作用域可以理解为一块空间这块空间的数据是可以共享的。通俗点来说作用域就类似于一个房子房子中的东西归里面的所有人共享其他房子的人无法获取。
4.1 函数为作用域
Python以函数为作用域所以在函数内创建的所有数据可以此函数中被使用无法在其他函数中被使用。
def func():name 武沛齐data_list [11,22,33,44]print(name,data_list)age 20print(age)def handler():age 18print(age)func()
handler()学会分析代码了解变量到底属于哪个作用域且是否可以被调用
def func():name 武沛齐age 29print(age)data_list [11,22,33,44]print(name,data_list)for num in range(10):print(num)print(num)if 1 1:value adminprint(value)print(value)if 1 2:max_num 10print(max_num)print(max_num)def handler():age 18print(age)handler()
func()4.2 全局和局部
Python中以函数为作用域函数的作用域其实是一个局部作用域。
goods [{name: 电脑, price: 1999},{name: 鼠标, price: 10},{name: 游艇, price: 20},{name: 美女, price: 998}
]
for index in range(len(goods)):item goods[index]print(index 1, item[name], item[price])while True:num input(请输入要选择的商品序号(Q/q)) # 1if num.upper() Q:breakif not num.isdecimal():print(用输入的格式错误)breaknum int(num)send_email()if num 4 or num 0:print(范围选择错误)breaktarget_index num - 1choice_item goods[target_index]print(choice_item[name], choice_item[price])send_email()# 全局变量变量名大写
COUNTRY 中国
CITY_LIST [北京,上海,深圳]def download():# 局部变量url http://www.xxx.com...def upload():file_name rose.zip...
COUNTRY和CITY_LIST是在全局作用域中全局作用域中创建的变量称之为【全局变量】可以在全局作用域中被使用也可以在其局部作用域中被使用。
download和upload函数内部维护的就是一个局部作用域在各自函数内部创建变量称之为【局部变量】且局部变量只能在此作用域中被使用。局部作用域中想使用某个变量时寻找的顺序为优先在局部作用域中寻找如果没有则去上级作用域中寻找。
注意全局变量一般都是大写。
示例1在局部作用域中读取全局作用域的变量。
COUNTRY 中国
CITY_LIST [北京,上海,深圳]def download():url http://www.xxx.comprint(url)print(COUNTRY)print(CITY_LIST)def upload():file_name rose.zipprint(file_name)print(COUNTRY)print(CITY_LIST)print(COUNTRY)
print(CITY_LIST)
downlowd()
upload()print(file_name) # 报错
print(url) # 报错示例2局部作用域和全局作用域变量同名这算啥
COUNTRY 中国
CITY_LIST [北京,上海,深圳]def download():url http://www.xxx.comCITY_LIST [河北,河南,山西]print(url)print(COUNTRY)print(CITY_LIST)def upload():file_name rose.zipprint(COUNTRY)print(CITY_LIST)print(COUNTRY)
print(CITY_LIST)
download()
upload()COUNTRY 中国
CITY_LIST [北京,上海,深圳]def download():url http://www.xxx.comCITY_LIST [河北,河南,山西]print(url)print(COUNTRY)print(CITY_LIST)def upload():file_name rose.zipprint(COUNTRY)print(CITY_LIST)print(COUNTRY)
print(CITY_LIST)
download()
upload()COUNTRY 中华人民共和共国
CITY_LIST [11,22,33]download()
upload()# 输出
中国
[北京,上海,深圳]
http://www.xxx.com
中国
[河北,河南,山西]
中国[北京,上海,深圳]
http://www.xxx.com
中华人民共和共国
[河北,河南,山西]
中华人民共和共国
[11,22,33]4.3 global关键字 默认情况下在局部作用域对全局变量只能进行读取和修改内部元素可变类型无法对全局变量进行重新赋值。 读取 COUNTRY 中国
CITY_LIST [北京,上海,深圳]def download():url http://www.xxx.comprint(COUNTRY)print(CITY_LIST)download()修改内部元素可变类型 COUNTRY 中国
CITY_LIST [北京,上海,深圳]def download():url http://www.xxx.comprint(CITY_LIST)CITY_LIST.append(广州)CITY_LIST[0] 南京print(CITY_LIST)download()无法对全局变量重新赋值 COUNTRY 中国
CITY_LIST [北京,上海,深圳]def download():url http://www.xxx.com# 不是对全部变量赋值而是在局部作用域中又创建了一个局部变量 CITY_LIST 。CITY_LIST [河北,河南,山西]print(CITY_LIST)def upload():file_name rose.zipprint(COUNTRY)print(CITY_LIST)download()
upload()如果想要在局部作用域中对全局变量重新赋值则可以基于 global关键字实现例如
COUNTRY 中国
CITY_LIST [北京,上海,深圳]def download():url http://www.xxx.comglobal CITY_LISTCITY_LIST [河北,河南,山西]print(CITY_LIST)global COUNTRYCOUNTRY 中华人民共和国print(COUNTRY)def upload():file_name rose.zipprint(COUNTRY)print(CITY_LIST)download()
upload()总结 函数参数传递的是内存地址。 想重新创建一份数据再传递给参数可以手动拷贝一份。 特殊参数是动态参数时通过*或**传参时会将数据循环添加到参数中类似于拷贝一份 def fun(*args, **kwargs):print(args, kwargs)fun(*[11, 22, 33], **{k1: 1, k2: 2})函数的返回值也是内存地址。函数执行完毕后其内部的所有变量都会被销毁引用计数器为0时数据也销毁 def func():name [11,22,33]data namefunc()def func():name [11,22,33]return namedata func()
while True:print(data)当函数的参数有默认值 默认值是可变类型 函数内部会修改内部元素有坑 # 内部会维护一个列表 []只要b不传值则始终使用都是这个列表。
def func(a,b[]):b.append(a)定义函数写形式参数时可以使用*和**执行函数时也可以使用。 函数名其实也是个变量他也可以做列表、字典、集合等元素可哈希 函数名可以被重新赋值也可以做另外一个函数的参数和返回值。 掌握 print 和 return的区别学会分析代码的执行流程。 python是以函数为作用域。 在局部作用域中寻找某数据时优先用自己的自己没有就在上级作用域中寻找。 基于 global关键字可以在局部作用域中实现对全局作用域中的变量全局变量重新赋值。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/920174.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!