python-函数进阶-动态传参,名称空间,作用域的问题
一.函数的动态的动态参数
动态参数分为两种:动态接收位置参数、动态接收关键字参数。
1.*args 位置参数动态传参
# 顺序: 位置参数=>*args(arguments) => 默认值参数
# * 在这里表示接收位置参数的动态传参, 接收到的是元组
def chi(name,*food, location="天津"): # 参数名是food *表示动态传参
print(location)
print(name+"要吃", food) chi("juan","驴打滚","二姑包子","桂顺斋","长春") #长春
#juan要吃("驴打滚","二姑包子","桂顺斋")
动态接收参数的时候要注意:动态参数必须在位置参数后面。具体请看下面几个示例:
def chi(*food, a, b):
print("我要吃", food, a, b)
chi("大米饭", "小米饭", "黄瓜", "茄子")
# 这时程序会报错,因为前面传递的所有位置参数都被*food接收了,a和b永远接收不到参数
# TypeError: chi() missing 2 required keyword-only arguments: 'a' and 'b' # 所以上例可以改成以下代码
def chi(*food,a,b):
print("我要吃",food,a,b)
chi("大米饭","小米饭",a="黄瓜",b="茄子") # 必须用关键字参数来指定
# 这时候a和b就有值了,但是这样写的话位置参数就不能用了, # 所以,我们要先写位置参数,然后再用动态参数
def chi(a,b,*food):
print("我要吃",a,b,food)
chi("大米饭","小米饭","馒头","面条")
# 结果为:我要吃 大米饭 小米饭 ('馒头', '面条')
# 前面两个参数用位置参数来接收,后面的参数用动态参数接收
def chi(a,b,c="馒头",*food):
print(a,b,c,food)
chi("香蕉","菠萝") # 香蕉 菠萝 馒头 ()默认值生效
chi("香蕉","菠萝","葫芦娃") # 香蕉 菠萝 葫芦娃() 默认值不生效
chi("香蕉","菠萝","葫芦娃","口罩") # 香蕉 菠萝 葫芦娃("口罩",)默认值不生效
# 我们发现默认值参数写在动态参数前面,默认值只有一种情况可能会生效。
# 即默认值生效时,其后的动态参数接收的参数一定是0个 def chi(a,b,*food,c="娃哈哈"):
print(a,b,food,c)
chi("香蕉","菠萝") #香蕉 菠萝 ()娃哈哈 你默认值生效
chi("香蕉","菠萝","葫芦娃") #香蕉 菠萝 ("葫芦娃",) 娃哈哈 默认值生效
chi("香蕉","菠萝","葫芦娃","口罩") #香蕉 菠萝 ("葫芦娃","口罩")娃哈哈 默认值生效
# 将默认值参数放在动态参数之后,我们发现所有的默认值都生效了,
# 这时候如果不给出关键字传参,那么你的默认值是永远都生效的。
综上可得参数顺序:位置参数,*args(动态接收位置参数),默认值参数
2,动态接收关键字参数 **kwargs
在python中可以动态传参,但是*args这种情况只能接收位置参数,无法接收关键字参数 使用关键字参数的动态传参:就是用**kwargs来接收动态关键字参数,具体示例如下:
def func(**kwargs):
print(kwargs)
func(a=1,b=2,c=3) # 结果为:{'a': 1, 'b': 2, 'c': 3}
func(a=1,b=2) # 结果为:{'a': 1, 'b': 2}
# 这时候接收的是一个dict字典
最终可得形参顺序:位置参数 > *args > 默认值参数 > **kwargs,这四种参数可以任意进行使用。
# 如果想要接收所有的参数可以这样写
# 当你不知道需要需要传递多少参数的时候可这样写,
# 因为这样可以传递任意参数,即无敌
def func(*args,**kwargs):
print(args,kwargs)
func("麻花藤","马云",wtf="胡辣汤")
3,动态参数的聚合与实参的打散
综上可知,在形参位置上*表示把接收到的位置参数聚合(组合)成一个元组,**表示把接收到的关键字参数聚合(组合)成一个字典,那么在实参位置上给一个字符串,列表,元组或者集合(可迭代对象即可),并在其前面加个*表示把这个序列打散,如果是一个字典,则在其前面加上**。具体示例如下:
def fun(*args):
print(args)
lst = [1,4,7]
# fun(lst[0],lst[1],lst[2])
fun(*lst) # 可以使用*把一个列表按顺序打散
s = "臣妾做不到"
fun(*s) # 字符串也可以打散(可迭代对象即可) def fun(**kwargs):
print(kwargs)
dic = {"a":1,"b":2}
fun(**dic)
4,函数的注释(文档注释)
def chi(food,drink):
"""
这里是函数的注释,先写一下当前这个函数是干什么的,比如我这个函数就是一个吃
:param food: 参数food是什么意思
:param drink: 参数drink是什么意思
:return: 返回的是什么东东
"""
print(food,drink)
return "very good"
二、命名空间
def fun():
a =10
print(a)
fun()
print(a) # a不存在了已经
命名空间的分类:
1,全局命名空间-->我们直接在py文件中,函数外声明的变量都属于全局命名空间;
2,局部命名空间-->在函数中声明的变量会放在局部命名空间;
3,内置命名空间 -->存放python解释器为我们提供的名字,如int,str,list这些都是内置命名空间;
加载顺序:
1,内置命名空间
2,全局命名空间
3,局部命名空间(函数被执行的时候)
取值顺序:
1,局部命名空间
2,全局命名空间
3,内置命名空间
a = 10
def dunc():
a = 20
print(a)
dunc() #结果为:20
作用域:作用域就是作用范围,按照生效范围来看分为全局作用域和局部作用域。
全局作用域:包含内置命名空间和全局命名空间,在整个文件的任何位置都可以使用(遵循从上到下逐行执行);
局部作用域:在函数内部可以使用;
我们可以通过globals()函数来查看全局作用域中的内容,也可以通过locals()来查看局部作用域中的变量和函数信息,具体示例如下:
a = 10
def func():
a = 40
b = 20
def abc():
print("哈哈")
print(a,b) # 这里使用的是局部作用域
print(globals()) #打印全局作用域中的内容
print(locals()) #打印局部作用域中的内容
func()
三,函数的嵌套
1,只要遇见了( )就是函数的调用,如果没有( )就不是函数的调用。
2,函数的执行顺序,具体示例如下:
#函数的嵌套
def fun2():
print(222)
def fun3():
print(666)
print(444)
fun3()
print(888)
print(33)
fun2()
print(555)
# 结果为:
# 33
# 222
# 444
# 666
# 888
#
四、关键字global和nonlocal
现在我们写这样一个代码,首先在全局声明一个变量,然后在局部调用这个变量,并改变这个变量的值,具体如下:
a = 10
def func():
global a # 这里用的a是全局的
a = 20
print(a)
func()
print(a) # 结果为:20 20 def func():
global a #加global 表示不在局部创建这个变量,而是直接使用全局的a
# 若不存在全局变量a,则创建一个全局变量a
a = 28
print(a)
func()
print(a) # 结果为:28 28
global:
1,声明一个全局变量;
2,在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字);
def func():
global a
a = 3
func()
print(a) # 结果为:3 count = 1
def search():
global count
count = 2
search()
print(count) # 结果为:2
注意:对可变数据类型(list,dict,set)可以直接引用,不用通过global也能改变。具体如下:
li = [1,2,3]
dic = {'a':'b'}
def change():
li.append('a')
dic['q'] = 'g'
print(dic)
print(li)
change()
print(li)
print(dic)
# 结果为:
# {'a': 'b', 'q': 'g'}
# [1, 2, 3, 'a']
# [1, 2, 3, 'a']
# {'a': 'b', 'q': 'g'}
nonlocal :
1,不能修改全局变量;
2,在局部作用域中,对父级作用域(或者更外层作用域且非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。具体示例如下:
a = 10
def func1():
a = 20
def func2():
nonlocal a
a = 30
print(a)
func2()
print(a)
func1()
# 结果:
# 加了nonlocal
#
#
# 不加nonlocal
#
#
练习,如果嵌套了很多层,会是一种什么效果,分析明白,那么作用域,global ,nonlocal 就没问题了:
a = 1
def fun_1():
a = 2
def fun_2():
nonlocal a
a = 3
def fun_3():
a = 4
print(a)
print(a)
fun_3()
print(a)
print(a)
fun_2()
print(a)
print(a)
fun_1()
print(a)
# 结果:
#
#
#
#
#
#
python-函数进阶-动态传参,名称空间,作用域的问题的更多相关文章
- python函数的动态传参.作用域与命名空间
一.动态传参1.*表示动态传参. 可以接受所有的位置参数传参的时候自动的把实参打包成元组 交给形参 def chi(*food): print(food) chi() # 动态传参可以不传参数 chi ...
- python之路--动态传参,作用域,函数嵌套
一 . 动态传参(重点) * , ** * 与 ** * 在形参位置. * 表示不定参数, 接收的是位置参数 接收到的位置参数的动态传参: 都是元组 def eat(*food): # 在形参这里 ...
- python记录_day10 动态传参 命名空间 作用域
一.动态传参 动态传参用到 *args 和 **kwargs ,*号表示接收位置参数,args是参数名:**表示接收关键字参数,kwargs是参数名 def chi(*food): print(foo ...
- Python函数定义及传参方式
主要内容: 1.函数初识 2.函数传参方式 (1)位置参数 (2)默认参数 (3)关键参数 (4)非固定传参 一.函数初识 1. ...
- python函数关键字实参传参
#!/usr/bin/python #coding=utf-8 #好好学习,天天向上 def describe_pet(type,name): print(f"i have a {type} ...
- python函数位置实参传参
#!/usr/bin/python #coding=utf-8 #好好学习,天天向上 def describe_pet(type,name): print(f"i have a {type} ...
- python(动态传参、命名空间、函数嵌套、global和nonlocal关键字)
一.函数的动态传参 1.*args位置参数动态传参 def chi(*food): print(food) chi("烧烤","火锅","虾吃虾涮&q ...
- python-函数-动态传参,作用域的问题,函数嵌套,global nonlocal
⼀. 函数参数--动态传参 之前我们说过了传参, 如果我们需要给⼀个函数传参, ⽽参数⼜是不确定的. 或者我给⼀个 函数传很多参数, 我的形参就要写很多, 很⿇烦, 怎么办呢. 我们可以考虑使⽤动态参 ...
- 函数动态传参,命名空间,gloabal,nonlocal关键字
一.函数参数->动态传参(形参的第三种) 动态参数分为两种: 1)动态接收位置参数 普通的位置传参: def func(quality_food,junk_food): print('我要吃', ...
随机推荐
- window上安装rabbitMQ
win7下安装RabbitMQ http://my.oschina.net/ydsakyclguozi/blog/528835?fromerr=q7m1OxxF 前辈总结的特别详细.
- 【 spring配置文件详解】
转自: http://book.51cto.com/art/201004/193743.htm Spring配置文件是用于指导Spring工厂进行Bean生产.依赖关系注入(装配)及Bean实例分发的 ...
- codeforces B. Roma and Changing Signs 解题报告
题目链接:http://codeforces.com/problemset/problem/262/B 题目意思:给出 n 个数和恰好一共要做的操作总数k.通过对n个数进行k次操作,每次操作可以把a[ ...
- hdu 2188 悼念512汶川大地震遇难同胞——选拔志愿者(Bash Game)
题意:从0开始捐款,每次不超过m元,首先达到n元的获胜 思路:等同于从n开始,每次取不超过m,首先达到0的获胜.(Bash Game) #include<iostream> #includ ...
- JAVA基础细谈
JAVA基础细谈 一. 源文件和编译后的类文件 源文件的本质就是程序文件,是程序员编写,是人看的.而编译后的类文件是给电脑看的文件.一个类就是一个文件,无论这个类写在哪里,编译以后都是一个文件 ...
- hdu-4991 Ordered Subsequence(dp+树状数组)
题目链接: Ordered Subsequence Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- eclipse 查找controller
一.打开eclipse: 二.同时按住Ctrl + Shift + R ; 弹出框如下: 在红色输入框内输入controller 名字即可. 查找控制器里面的方法:Ctrl + O
- ubuntu12.04下有线网无电缆插入问题
解决方案: 1.查看是否没装网卡驱动: 2.检查网卡是否损坏: 3.检查网线是否损坏(注意:有时候不一定是网线损坏了,而是网线太细了,导通性不好.本人用细网线试了一下,windows下面可以连接网络, ...
- HDOJ-2058
The sum problem Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- 3.1-3.3 HBase Shell创建表
一.HBase Shell创建表 1.HBASE shell命令 ## hbase(main):001:0> create_namespace 'ns1' //创建命名空间:ns1 hbase( ...