决定你上限的因素是什么? 毅力,坚持 1.目标不要太大,不要定太多,需要有人监督 2.定期反思,总结。 6:30 起床 老男孩 架构师
1. 今日内容
1.1 函数的参数
*的魔性用法
函数形参最终顺序
1.2名称空间
全局名称空间,局部名称空间,内置名称空间
取值顺序与加载顺序
作用域
内置函数:globals() locals()
1.3 高阶函数(函数的嵌套)
1.4关键字:global nonlocal
2. 内容详细
2.1 函数的参数
昨天我们从形参角度,讲了两种参数,一个是位置参数,位置参数主要是实参与形参从左至右一一对应,一个是默认值参数,默认值参数,如果实参不传参,则形参使用默认参数。那么无论是位置参数,还是默认参数,函数调用时传入多少实参,我必须写等数量的形参去对应接收, 如果不这样,那么就会报错:
def eat(a,b,c,): print('我请你吃:',a,b,c) eat('蒸羊羔','蒸熊掌','蒸鹿尾儿','烧花鸭') # 报错
如果我们在传参数的时候不很清楚有哪些的时候,或者说给一个函数传了很多实参,我们就要对应写很多形参,这样很麻烦,怎么办?,我们可以考虑使用动态参数也叫万能参数
2.11 形参的第三种:动态参数
动态参数分为两种:动态接受位置参数 *args,动态接收关键字参数**kwargs.
动态接收位置参数:*args 1星位元
我们按照上面的例子继续写,如果我请你吃的内容很多,但是我又不想用多个参数接收,那么我就可以使用动态参数*args
def eat(*args): print('我请你吃:',args) eat('蒸羊羔儿','蒸熊掌','蒸鹿尾儿','烧花鸭','烧雏鸡','烧子鹅') # 运行结果: #我请你吃: ('蒸羊羔儿', '蒸熊掌', '蒸鹿尾儿', '烧花鸭', '烧雏鸡', '烧子鹅')
解释一下上面参数的意义:首先来说args,args就是一个普通的形参,但是如果你在args前面加一个 *,那么就拥有了特殊的意义:在python中除了表示乘号,他是有魔法的。*args,这样设置形参,那么这个形参会将实参所有的位置参数接收,放置在一个元组中,并将这个元组赋值给args这个形参,这里起到魔法效果的是 * 而不是args,a也可以达到刚才效果,但是我们PEP8规范中规定就使用args,约定俗成的。
练习:传入函数中数量不定的int型数据,函数计算所有数的和并返回。
def my_max(*args):
n = 0
for i in args:
n += i
return n
print(my_max(1,2,3,4,5)) #15
动态接收关键字参数: **kwargs 2星关典
实参角度有位置参数和关键字参数两种,python中既然有*args可以接受所有的位置参数那么肯定也有一种参数接受所有的关键字参数,那么这个就是kwargs,同理这个是具有魔法用法的,kwargs约定俗成使用作为形参。举例说明:**kwargs,是接受所有的关键字参数然后将其转换成一个字典赋值给kwargs这个形参。
def func(**kwargs): print(kwargs) # {'name': '太白金星', 'sex': '男'} func(name='太白金星',sex='男')
我们看一下动态参数的完成写法:
def func(*args,**kwargs): print(args) # ('蒸羊羔儿', '蒸熊掌', '蒸鹿尾儿') print(kwargs) # {'name': '太白金星', 'sex': '男'} func('蒸羊羔儿', '蒸熊掌', '蒸鹿尾儿',name='太白金星',sex='男')
如果一个参数设置了动态参数,那么他可以接受所有的位置参数,以及关键字参数,这样就会大大提升函数拓展性,针对于实参参数较多的情况下,解决了一一对应的麻烦。
2.12 * 的魔性用法
刚才我们研究了动态参数,其实有的同学对于魔法用法 * 比较感兴趣,那么那的魔性用法不止这么一点用法,我们继续研究:
函数中分为打散和聚合。
函数外可以处理剩余的元素。
函数的打散和聚合
聚合
刚才我们研究了,在函数定义时,如果我只定义了一个形参称为args,那么这一个形参只能接受几个实参? 是不是只能当做一个位置参数对待?它只能接受一个参数:
def eat(args): print('我请你吃:',args) # 我请你吃: 蒸羊羔儿 eat('蒸羊羔儿')
但是如果我给其前面加一个* 那么args可以接受多个实参,并且返回一个元组,对吧? (**kwargs也是同理将多个关键字参数转化成一个字典返回)所以在函数的定义时: * 起到的是聚合的作用。
打散
此时不着急给大家讲这个打散,而是出一个小题:你如何将三个数据(这三个数据都是可迭代对象类型)s1 = 'alex',l1 = [1, 2, 3, 4], tu1 = ('武sir', '太白', '女神',)的每一元素传给动态参数*args?(就是args最终得到的是 ('a','l','e','x', 1, 2, 3, 4,'武sir', '太白', '女神',)?有人说这还不简单么?我直接传给他们不就行了?
s1 = 'alex' l1 = [1, 2, 3, 4] tu1 = ('武sir', '太白', '女神',) def func(*args): print(args) # ('alex', [1, 2, 3, 4], ('武sir', '太白', '女神')) func(s1,l1,tu1)
这样肯定是不行,他会将这个三个数据类型当成三个位置参数传给args,没有实现我的要求。
好像你除了直接写,没有别的什么办法,那么这里就得用到我们的魔法用法 :*
s1 = 'alex' l1 = [1, 2, 3, 4] tu1 = ('武sir', '太白', '女神',) def func(*args): print(args) # ('a', 'l', 'e', 'x', 1, 2, 3, 4, '武sir', '太白', '女神') func(*s1,*l1,*tu1)
你看此时是函数的执行时,我将你位置参数的实参(可迭代类型)前面加上*,相当于将这些实参给拆解成一个一个的组成元素当成位置参数,然后传给args,这时候这个好像取到的是打散的作用。所以在函数的执行时:,*起到的是打散的作用。
dic1 = {'name': '太白', 'age': 18}
dic2 = {'hobby': '喝茶', 'sex': '男'}
def func(**kwargs):
print(kwargs) # {'name': '太白', 'age': 18, 'hobby': '喝茶', 'sex': '男'}
func(**dic1,**dic2)
*处理剩下的元素
*除了在函数中可以这样打散,聚合外,函数外还可以灵活的运用:
# 之前讲过的分别赋值 a,b = (1,2) print(a, b) # 1 2
# 其实还可以这么用: a,*b = (1, 2, 3, 4,) print(a, b) # 1 [2, 3, 4]
*rest,a,b = range(5) print(rest, a, b) # [0, 1, 2] 3 4
print([1, 2, *[3, 4, 5]]) # [1, 2, 3, 4, 5]
2.13 形参的顺序
到目前为止,从形参的角度我们讲了位置参数,默认值参数,动态参数*args,**kwargs,还差一种参数,需要讲完形参顺序之后,引出。先不着急,我们先看看已经讲的这些形参他的排列顺序是如何的呢?
首先,位置参数,与默认参数他两个的顺序我们昨天已经确定了,位置参数必须在前面,即 :位置参数,默认参数。
那么动态参数*args,**kwargs放在哪里呢?
动态参数*args,肯定不能放在位置参数前面,这样我的位置参数的参数就接收不到具体的实参了:
# 这样位置参数a,b始终接收不到实参了,因为args全部接受完了 def func(*args,a,b,sex='男'): print(args) print(a,b) func(1, 2, 3, 4, 5)
那么动态参数必须在位置参数后面,他可以在默认参数后面么?
# 这样也不行,我的实参的第三个参数始终都会将sex覆盖掉,这样失去了默认参数的意义。 def func(a,b,sex='男',*args,): print(args) # (4, 5) print(sex) # 3 print(a,b) # 1 2 func(1, 2, 3, 4, 5)
所以*args一定要在位置参数与默认值参数中间:位置参数,*args,默认参数。
那么我的kwargs放在哪里?kwargs可以放在默认参数前面么?
# 直接报错:因为**kwargs是接受所有的关键字参数,如果你想改变默认参数sex,你永远也改变不了,因为 # 它会先被**kwargs接受。 def func(a,b,*args,**kwargs,sex='男',): print(args) # (4, 5) print(sex) # 3 print(a,b) # 1 2 print(kwargs) func(1, 2, 3, 4, 5)
所以截止到此:所有形参的顺序为:位置参数,*args,默认参数,**kwargs。
2.14 形参的第四种参数:仅限关键字参数
仅限关键字参数是python3x更新的新特性,他的位置要放在*args后面,kwargs前面(如果有kwargs),也就是默认参数的位置,它与默认参数的前后顺序无所谓,它只接受关键字传的参数:
# 这样传参是错误的,因为仅限关键字参数c只接受关键字参数 def func(a,b,*args,c): print(a,b) # 1 2 print(args) # (4, 5) # func(1, 2, 3, 4, 5) # 这样就正确了: def func(a,b,*args,c): print(a,b) # 1 2 print(args) # (3, 4) print(5) func(1, 2, 3, 4, c=5)
这个仅限关键字参数从名字定义就可以看出他只能通过关键字参数传参,其实可以把它当成不设置默认值的默认参数而且必须要传参数,不传就报错。
所以形参角度的所有形参的最终顺序为:位置参数,*args(动态接收位置参数),默认参数,仅限关键字参数,**kwargs(动态接收关键字参数)
喂(位置参数)动(*args)物,末(默认参数)紧观(仅限关键字参数)动参(**kwargs)
课间考一道题: def foo(a,b,*args,c,sex=None,**kwargs): print(a,b) print(c) print(sex) print(args) print(kwargs) # foo(1,2,3,4,c=6) # foo(1,2,sex='男',name='alex',hobby='old_woman') # foo(1,2,3,4,name='alex',sex='男') # foo(1,2,c=18) # foo(2, 3, [1, 2, 3],c=13,hobby='喝茶') # foo(*[1, 2, 3, 4],**{'name':'太白','c':12,'sex':'女'})
2.2 名称空间,作用域
2.21 名称空间:
接下来我们讲的内容,理论性的偏多,就是从空间角度,内存级别去研究python。首先我们看看什么是全局名称空间:
在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内存, 表示这个函数存在了, 至于函数内部的变量和逻辑, 解释器是不关心的. 也就是说一开始的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间. 随着函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空.
我们首先回忆一下Python代码运行的时候遇到函数是怎么做的,从Python解释器开始执行之后,就在内存中开辟里一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征性的将函数名读如内存,表示知道这个函数存在了,至于函数内部的变量和逻辑,解释器根本不关心。
等执行到函数调用的时候,Python解释器会再开辟一块内存来储存这个函数里面的内容,这个时候,才关注函数里面有哪些变量,而函数中的变量回储存在新开辟出来的内存中,函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。
我们给这个‘存放名字与值的关系’的空间起了一个名字-------命名空间。
代码在运行开始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;
在函数的运行中开辟的临时的空间叫做局部命名空间也叫做临时名称空间。
现在我们知道了,py文件中,存放变量与值的关系的一个空间叫做全局名称空间,而当执行一个函数时,内存中会临时开辟一个空间,临时存放函数中的变量与值的关系,这个叫做临时名称空间,或者局部名称空间。
其实python还有一个空间叫做内置名称空间:内置名称空间存放的就是一些内置函数等拿来即用的特殊的变量:input,print,list等等,所以,我们通过画图捋一下:

那么这就是python中经常提到的三个空间。
总结:
1. 全局命名空间--> 我们直接在py文件中, 函数外声明的变量都属于全局命名空间
2. 局部命名空间--> 在函数中声明的变量会放在局部命名空间
3. 内置命名空间--> 存放python解释器为我们提供的名字, list, tuple, str, int这些都是内置命名空间
2.22 加载顺序:
所谓的加载顺序,就是这三个空间加载到内存的先后顺序,也就是这个三个空间在内存中创建的先后顺序,你想想他们能是同时创建么?肯定不是的,那么谁先谁后呢?我们捋顺一下:在启动python解释器之后,即使没有创建任何的变量或者函数,还是会有一些函数直接可以用的比如abs(-1),max(1,3)等等,在启动Python解释器的时候,就已经导入到内存当中供我们使用,所以肯定是先加载内置名称空间,然后就开始从文件的最上面向下一行一行执行,此时如果遇到了初始化变量,就会创建全局名称空间,将这些对应关系存放进去,然后遇到了函数执行时,在内存中临时开辟一个空间,加载函数中的一些变量等等。所以这三个空间的加载顺序为:内置命名空间(程序运行伊始加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载。
2.23 取值顺序:
取值顺序就是引用一个变量,先从哪一个空间开始引用。这个有一个关键点:从哪个空间开始引用这个变量。我们分别举例说明:
# 如果你在全局名称空间引用一个变量,先从全局名称空间引用,全局名称空间如果没有,才会向内置名称空间引用。 input = 666 print(input) # 666 # 如果你在局部名称空间引用一个变量,先从局部名称空间引用, # 局部名称空间如果没有,才会向全局名称空间引用,全局名称空间在没有,就会向内置名称空间引用。 input = 666 print(input) # 666 input = 666 def func(): input = 111 print(input) # 111 func()
所以空间的取值顺序与加载顺序是相反的,取值顺序满足的就近原则,从小范围到大范围一层一层的逐步引用。
加(加载顺序)内(内置命名空间)全(全局命名空间)局(局部命名空间)

2.24 作用域
作用域就是作用范围, 按照生效范围来看分为全局作用域和局部作用域
全局作用域: 包含内置命名空间和全局命名空间. 在整个文件的任何位置都可以使用(遵循 从上到下逐⾏执行).
局部作用域: 在函数内部可以使用.
作⽤域命名空间:
1. 全局作用域: 全局命名空间 + 内置命名空间
2. 局部作⽤域: 局部命名空间
2.25 内置函数globals(),locals()
这两个内置函数放在这里讲是在合适不过的,他们就直接可以反映作用域的内容,有助于我们理解作用域的范围。
globals(): 以字典的形式返回全局作用域所有的变量对应关系。
locals(): 以字典的形式返回当前作用域的变量的对应关系。
这里一个是全局作用域,一个是当前作用域,一定要分清楚,接下来,我们用代码验证:
# 在全局作用域下打印,则他们获取的都是全局作用域的所有的内容。 a = 2 b = 3 print(globals()) print(locals()) ''' {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001806E50C0B8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/lnh.python/py project/teaching_show/day09~day15/function.py', '__cached__': None, 'a': 2, 'b': 3} ''' # 在局部作用域中打印。 a = 2 b = 3 def foo(): c = 3 print(globals()) # 和上面一样,还是全局作用域的内容 print(locals()) # {'c': 3} foo()
2.3 高阶函数(函数的嵌套)
其实我们见到了嵌套这个词不陌生,之前我们讲过列表的嵌套,列表的嵌套就是一个列表中还有列表,可能那个列表中还有列表......那么顾名思义,函数的嵌套,就是一个函数中,还有函数。
想要玩明白函数的嵌套,关键点:只要遇见了函数名+()就是函数的调用. 如果没有就不是函数的调用,吃透这一点就算明白了。那么我们举例练习:找同学依次说出下面代码的执行顺序
# 例1: def func1(): print('in func1') print(3) def func2(): print('in func2') print(4) func1() print(1) func2() print(2) # 例2: def func1(): print('in func1') print(3) def func2(): print('in func2') func1() print(4) print(1) func2() print(2) # 例3: def fun2(): print(2) def fun3(): print(6) print(4) fun3() print(8) print(3) fun2() print(5)
2.4 关键字:global、nonlocal
global
讲这个关键字之前,先给大家看一个现象:
a = 1 def func(): print(a) func() a = 1 def func(): a += 1 # 报错 func()
局部作用域对全局作用域的变量(此变量只能是不可变的数据类型)只能进行引用,而不能进行改变,只要改变就会报错,但是有些时候,我们程序中会遇到局部作用域去改变全局作用域的一些变量的需求,这怎么做呢?这就得用到关键字global:
global第一个功能:在局部作用域中可以更改全局作用域的变量。
count = 1 def search(): global count count = 2 search() print(count)
利用global在局部作用域也可以声明一个全局变量。
def func(): global a a = 3 func() print(a)
所以global关键字有两个作用:
1,声明一个全局变量。
2,在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)。
nonlocal
nonlocal是python3x新加的功能,与global用法差不多,就是在局部作用域如果想对父级作用域的变量进行改变时,需要用到nonlocal,当然这个用的不是很多,了解即可。
def add_b(): b = 42 def do_global(): b = 10 print(b) def dd_nonlocal(): nonlocal b b = b + 20 print(b) dd_nonlocal() print(b) do_global() print(b) add_b()
nonlocal的总结:
1,不能更改全局变量。
2,在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
nonlocal 只能操作局部名称空间里的。如果把count放到全局变量中,或者用glocal 都会报错。
# def func1(): # print(111) # def func2(): # print(222) # func1() # print(333) # print(666) # func2() # print(555) # # def func1(): # print(222) # def func2(): # print(333) # print(111) # func2() # print(666) # func1() # 222 111 333 666 # global nonlocal # 局部名称空间 对全局名称空间的变量可以引用,但是不能改变。 # count = 1 # def func1(): # count = 2 # print(count) # func1() # count = 1 # def func1(): # # count = 3 # count = count + 1 # local variable 'count' referenced before assignment # print(count) # func1() # 如果你在局部名称空间 对一个变量进行修改,那么解释器会认为你的这个变量在局部中已经定义了, # 但是对于上面的例题,局部中没有定义,所以他会报错, # global # 1,在局部名称空间声明一个全局变量。 # def func2(): # global name # name = 'alex' # func2() # print(name) # 2,在局部名称空间可以对全局变量进行修改。 # count = 1 # def func1(): # global count # count = count + 1 # print(count) # func1() # print(count) # nonlocal # def func1(): # count = 666 # def func2(): # print(count) # func2() # func1() # nonlocal # 子函数对父函数的变量进行修改。 # 此变量不能是全局变量。 # 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改, # 并且引用的哪层,从那层及以下此变量全部发生改变。 def func1(): count = 666 def inner(): print(count) def func2(): nonlocal count count += 1 print('func2',count) func2() print('inner',count) inner() print('func1',count) func1() # 666 func2 667 inner 667 func1 667 #
Python LEGB规则
本篇总结了Python中的命名空间及LEGB原则
写在前面的话
之所以有这篇总结,是因为在当初学习及使用Python的过程中发现,理解Python的LEGB原则是理解Python命名空间的关键,而理解Python的命名空间又是理解Python中许多语法规定的关键。所以,Python的LEGB原则就成为Python中一个非常核心的内容,因而,也就有了本篇。
OK,下面开始正文
----------------------傲娇的分割线--------------------------
1. 命名空间
先来一段概要总结:
白话一点讲:命名空间是对变量名的分组划分。
不同组的相同名称的变量视为两个独立的变量,因此隶属于不同分组(即命名空间)的变量名可以重复。
命名空间可以存在多个,使用命名空间,表示在该命名空间中查找当前名称。
虽然命名空间是一个跟具体语言无关的概念,但是,不同的语言由于机制不同,因此在表现上还是有差别的。例如下述Python的例子:
x = 10 def foo(): global x x += 1 print x
在这个例子中,使用函数外部的变量x之前需要使用global关键字。这在C++中是不需要的。
所以,在理解Python的命名空间时,不能C++的规则来套,因为语法规则属于机制的实现。
那么,如何理解Python的命名空间呢?
在C语言中,存在命名空间的概念,但是并没有提供对命名空间的支持,因此,在编写C程序的过程中,很容易发生名称碰撞(name collision),而避免这一问题,基本靠程序员自身来完成。为了解决这个问题C++中提供了namespace关键字支持。关于这个话题,可以参考这里。为了不分散话题,就不详细展开了。
根据我的经验,理解Python的命名空间,从变量入手是个不错的选择。
在C语言中,变量名是内存地址的别名。但是由于Python一切皆对象,所以在Python中变量名是字符串对象。
例如:
>>> a = 10
表示建立字符串对象a与Number对象10之间的对应关系。由于这是一种映射关系,所以,可以使用键-值的形式来表示,即{name : object}。
前面已经说过,命名空间是对变量名的分组划分,所以,Python的命名空间就是对许多键-值对的分组划分,即,键值对的集合,因此:
Python的命名空间是一个字典,字典内保存了变量名称与对象之间的映射关系
好了,到这里,终于可以引入本篇的重点LEGB,呼~
2. LEGB
LEGB含义解释:
L-Local(function);函数内的名字空间
E-Enclosing function locals;外部嵌套函数的名字空间(例如closure)
G-Global(module);函数定义所在模块(文件)的名字空间
B-Builtin(Python);Python内置模块的名字空间
前面讲到,Python的命名空间是一个字典,字典内保存了变量名称与对象之间的映射关系,因此,查找变量名就是在命名空间字典中查找键-值对。
Python有多个命名空间,因此,需要有规则来规定,按照怎样的顺序来查找命名空间,LEGB就是用来规定命名空间查找顺序的规则。
LEGB规定了查找一个名称的顺序为:local-->enclosing function locals-->global-->builtin

举个栗子来说明:
#!/usr/bin/env python # encoding: utf-8 x = 1 def foo(): x = 2 def innerfoo(): x = 3 print 'locals ', x innerfoo() print 'enclosing function locals ', x foo() print 'global ', x
运行结果:
locals 3 enclosing function locals 2 global 1
对上例稍加改动
#!/usr/bin/env python # encoding: utf-8 x = 1 def foo(): x = 2 def innerfoo(): # x = 3 #此处改动:注释掉 print 'locals ', x innerfoo() print 'enclosing function locals ', x foo() print 'global ', x
运行结果
locals 2 enclosing function locals 2 global 1
可以发现:当注释掉x = 3以后,函数innerfoo内部查找到的x是x = 2。
在上述两个例子中,从内到外,依次形成四个命名空间:
def innerfoo()::Local, 即函数内部命名空间;
def foo()::Enclosing function locals;外部嵌套函数的名字空间
module(文件本身):Global(module);函数定义所在模块(文件)的名字空间
Python内置模块的名字空间:Builtin
x = 3 属于函数内部命名空间,当被注释掉之后,函数innerfoo内部通过print x 使用x这个名称时,触发了名称查找动作。
首先在Local命名空间查找,没有找到,然后到Enclosing function locals命名空间查找,查找成功,然后调用。
写在最后
通过上面的分析可以发现,Python在确定一个变量的核心规则是LEGB,只有熟悉LEGB规则,才能清楚在程序执行过程中调用的变量究竟是什么。
#作业及默写 # 1,整理函数相关知识点,写博客。 # # 2,写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。 # 3,写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。 # # 4,写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。 # # 5,写函数,计算传入函数的字符串中,[数字]、[字母]、[空格] 以及 [其他]的个数,并返回结果。 # 6,写函数,接收两个数字参数,返回比较大的那个数字。 # # 7,写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。 # dic = {"k1": "v1v1", "k2": [11,22,33,44]} # PS:字典中的value只能是字符串或列表 # 8,写函数,此函数只接收一个参数且此参数必须是列表数据类型,此函数完成的功能是返回给调用者一个字典,此字典的键值对为此列表的索引及对应的元素。例如传入的列表为:[11,22,33] 返回的字典为 {0:11,1:22,2:33}。 # 9,写函数,函数接收四个参数分别是:姓名,性别,年龄,学历。用户通过输入这四个内容,然后将这四个内容传入到函数中,此函数接收到这四个内容,将内容追加到一个student_msg文件中。 # # 10,对第9题升级:支持用户持续输入,Q或者q退出,性别默认为男,如果遇到女学生,则把性别输入女。 # # 11,写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整个文件的批量修改操作(升级题)。 # 12,写一个函数完成三次登陆功能:(升级题,两天做完) # (1) 用户的用户名密码从一个文件register中取出。 # (2) register文件包含多个用户名,密码,用户名密码通过|隔开,每个人的用户名密码占用文件中一行。 # (3) 完成三次验证,三次验证不成功则登录失败,登录失败返回False。 # (4) 登陆成功返回True。 # 13,再写一个函数完成注册功能:(升级题,两天做完) # (1) 用户输入用户名密码注册。 # (2) 注册时要验证(文件regsiter中)用户名是否存在,如果存在则让其重新输入用户名,如果不存在,则注册成功。 # (3) 注册成功后,将注册成功的用户名,密码写入regsiter文件,并以 | 隔开。 # (4) 注册成功后,返回True,否则返回False。 # 明日默写。 # ①,return的作用。 # ②,传参的几种方法,每个都简单写一个代码。 # 如,实参,按位置传参。 # def func(x,y): # Pass # func(‘a’,’b’)
# 作业及默写 # 1,整理函数相关知识点,写博客。 # # 2,写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。 # def func(l):return l[::2] # print(func([1,2,3,4,5,6,7])) #[1, 3, 5, 7] # 3,写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。 # def func1(args): # if len(args)> 5: # print('大于') # else: # print('小于') # func1(['1234']) # 4,写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。 # def func(lst): # if len(lst)>2:lst = lst[0:2] # return lst # print(func(['111',2,3,4,5,6])) # # 5,写函数,计算传入函数的字符串中,[数字]、[字母]、[空格] 以及 [其他]的个数,并返回结果。 # def func(args):return len(args) # print(func('123123 rewq!!!!!')) # 6,写函数,接收两个数字参数,返回比较大的那个数字。 # def func6(x,y): # if x > y: # return x # else: # return y # print(func6(10,2)) # 7,写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。 # dic = {"k1": "v1v1", "k2": [11,22,33,44]} # PS:字典中的value只能是字符串或列表 # dic = {"k1": "v1v1", "k2": [11,22,33,44]} # dic1 ={} # def func(*args,**kwargs): # for i in dic: # dic1[i] = dic[i][:2] # print(dic1) # func(dic) # 8,写函数,此函数只接收一个参数且此参数必须是列表数据类型,此函数完成的功能是返回给调用者一个字典,此字典的键值对为此列表的索引及对应的元素。例如传入的列表为:[11,22,33] 返回的字典为 {0:11,1:22,2:33}。 # dic ={} # def func8(l): # for key,value in enumerate(l): # dic[key] = value # #print(value) # return dic # #return print(dic) # print(func8([11,22,33])) # 9,写函数,函数接收四个参数分别是:姓名,性别,年龄,学历。用户通过输入这四个内容,然后将这四个内容传入到函数中,此函数接收到这四个内容,将内容追加到一个student_msg文件中。 # def func9(*args): # with open('student_msg',encoding='utf-8',mode='a+') as f1: # for i in args: # #print(i) # f1.write(str(i)+'|') # f1.write('\n') # print('start') # func9('张三','男',19,'大学') # func9('张三1','男',21,'大学') # print('end') # """ # 张三|男|19|大学| # 张三1|男|21|大学| # """ # 10,对第9题升级:支持用户持续输入,Q或者q退出,性别默认为男,如果遇到女学生,则把性别输入女。 # while 1: # args = input('请输入').strip() # if args.upper() == 'Q':break # def func9(name,age,stu,sex='男'): # with open('student_msg',encoding='utf-8',mode='a+') as f1: # for i in args: # #print(i) # f1.write(str(i)+'|') # f1.write('\n') # print('start') # func9() # # print('end') # 11,写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整个文件的批量修改操作(升级题)。 # def func(filename,old,new): # # with open(filename,mode='r',encoding='utf-8') as f, open('%s.bak'%filename,mode='w',encoding='utf-8') as f2: # old = str(old) # new = str(new) # for line in f: # if old in line: # line = line.replace(old,new) # f2.write(line) # import os # os.remove(filename) # os.rename('%s.bak'%filename,filename) # func('study','函数','不错的哦') # 12,写一个函数完成三次登陆功能:(升级题,两天做完) # (1) 用户的用户名密码从一个文件register中取出。 # (2) register文件包含多个用户名,密码,用户名密码通过|隔开,每个人的用户名密码占用文件中一行。 # (3) 完成三次验证,三次验证不成功则登录失败,登录失败返回False。 # (4) 登陆成功返回True。 # def login(): # count = 4 # while 1 <count: # count -= 1 # username = input('用户名>>>').strip() # password = input('密码>>>').strip() # with open('register',mode='r',encoding='utf-8') as f1: # for line in f1: # user,pwd = line.strip().split('|') # if username == user and password == pwd: # print('True') # break # else: # print('False') # login() # 13,再写一个函数完成注册功能:(升级题,两天做完) # (1) 用户输入用户名密码注册。 # (2) 注册时要验证(文件regsiter中)用户名是否存在,如果存在则让其重新输入用户名,如果不存在,则注册成功。 # (3) 注册成功后,将注册成功的用户名,密码写入regsiter文件,并以 | 隔开。 # (4) 注册成功后,返回True,否则返回False。 # import os # def regsiter(): # # while 1: # username = input('请输入用户名>>>').strip() # with open('register', mode='r', encoding='utf-8') as f1: # for line in f1: # user, pwd = line.strip().split('|') # #print(user) # if username == user: # print('用户名存在请重新输入') # break # else: # password = input('请输入密码>>>').strip() # with open('register',mode='a+',encoding='utf-8') as f2: # size = os.path.getsize('register') # if size == 0: # f2.write('{}|{}\n'.format(username,password)) # else: # #f2.seek(0, 2) # f2.write('{}|{}\n'.format(username,password)) # return True # regsiter() # 明日默写。 # ①,return的作用。 # ②,传参的几种方法,每个都简单写一个代码。 # 如,实参,按位置传参。 # def func(x,y): # Pass # func(‘a’,’b’)
posted on
浙公网安备 33010602011771号