yaya

今天也要加油鸭!!!

day10

# day10

## 复习

```python
'''
1.可以循环登录注册,输入1代表选择登录功能,输入2代表注册功能,输入0代表退出,其他输入代表输入有误,重输
2.用户的账号密码信息存放在usr.txt文件中,保证用户注册成功后,重启系统,用户信息仍然保存
3.登录在账号验证通过才输入密码验证登录,账号验证三次失败自动进入注册功能,登录三次验证失败自动退出系统
4.第一次注册,文件写入 账号:密码 信息,再次注册追加写入 |账号:密码 信息

'''
# 获取文件中用户信息
def get_usr_map():
usr_map = {}
# 该函数所需参数与返回值
with open('usr.txt', 'r', encoding='utf-8') as f:
# abc:123|aaa:000
data = f.read()
if data:
k_vs = data.split('|') # [abc:123,aaa:000]
for k_v in k_vs: # abc:123
k, v = k_v.split(':')
usr_map[k] = v
return usr_map

# 写入用户信息
def set_usr(usr, pwd):
usr_map = get_usr_map()
with open('usr.txt', 'a', encoding='utf-8') as f:
if not usr_map: # 第一次写入信息
info = usr + ":" + pwd
else: # 再次写入信息
info = '|' + usr + ":" + pwd
f.write(info)

 

# 注册
def register():
print('注册页面')
usr_map = get_usr_map()
# 输入账号,账号已存在,重新输入
while True:
usr = input('usr: ')
if usr in usr_map:
print('usr exist')
continue
pwd = input('pwd: ')
# 账号合法,输入密码完成注册(将信息写入文件)
set_usr(usr, pwd)
return

# 登录
def login():
print('登录页面')
# 获取用户信息
usr_map = get_usr_map()

# 用户输入账号,错误三次进入注册
c1 = 0
while True:
if c1 >= 3: # 错误3次
print('usr error 3')
register()
return
# 账号错误判断
usr = input('usr: ')
if usr not in usr_map:
c1 += 1
else:
# 账号正确可以进入输入密码
break
# 账号正确,密码错误三次,退出系统
c2 = 0
while True:
if c2 >= 3: # 错误3次
print('pwd error 3')
# 要将is_over值修改为True
return True # 系统的is_over状态
pwd = input('pwd: ')
if pwd != usr_map.get(usr):
print('login error')
c2 += 1

# 账号密码均正确,登录成功
else:
print('login success')
return # 只结束登录
# return True # 结束登录还结束系统

 

 

# 启动系统
def start():
print("系统启动!")

# 登录失败是退出系统的需求,所以系统中的循环应该设置出口,所以才用变值
is_over = False
while not is_over:
tag = input("""请输入操作指令:
0:退出
1:登录
2:注册
>>>: """)
if tag.isdigit():
tag = int(tag)
if tag == 0:
break
elif tag == 1:
is_over = login()
elif tag == 2:
register()
else:
print("输入有误,请重新输入")

# 启动系统
start()


# 循环什么时候用定值True,什么时候有变值(True|False)
```

## 形参与实参

```python
# ***** 在函数定义()中出现的参数:形参就是在定义函数阶段括号内指定变量名,即形参本质就是变量名

def fn(a, b, c):
# a,b,c必须要从外界获取值,才用意义
print(a)
print(b)
print(c)
# 外部提前产生了的变量,内部可以使用
print(x)
print(y)
print(z)
# ***** 在函数调用()中出现的参数(外界实际存在的值):实参
# ***** 调用函数是,实参可以由 常量、变量、表达式或三种的组合

# x,y,z是实际存在的值
x = 10
y = 20
z = 30

# fn(10, 20, 30)
# fn(x, y, z)
fn(x + 10, y * 2, z / 5)

 

# ***** 形参与实参的关系:在调用函数时,会将实参(值)赋值给形参(变量名)
# 这种绑定关系在函数调用时临时生效的 在函数的外部不能直接使用函数的形参,原因:函数调用完毕后,形参被销毁了
# 函数体内可以return a,b,c返回的只是a,b,c的值,并不是a,b,c变量名,所以返回的值还要自己赋值绑定给三个变量名
# print(a)
# print(b)
# print(c)
```

## 实参的分类

```python

# 实参作用:为形参传递值

def fn1(a, b, c):
print(a, b, c)


# *****位置实参:在调用函数阶段,必须按照顺序,从左到右为形参传递值,一一对应形参值,多一个少一个都不行
fn1(10, 20, 30)
fn1(30, 20, 10)

# *****关键字实参:在调用阶段,按照key与value的形式指名道姓地为形参传值。可以不按顺序传递
fn1(a=10, b=20, c=30)
fn1(c=30, b=20, a=10)

# *****两者混用: 位置实参必须放到关键字实参前面,不能对一个形参重复赋值
# fn1(10, c=20, a=30) # 10按位置传参给a,a=30给a传参,c可以拿到20,但b没人传参
# TypeError:fn1() got multiple values for argument 'a' a被多次传值

# 合法传参
fn1(10, c=30, b=20)
fn1(10, b=30, c=20)


def fn2(a, b, c, d, e, f):
print(a, b, c, d, e, f)

fn2(10, 20, 30, e=100, f=500, d=200)
```

## 形参的分类

- 位置形参

```python
# 位置形参:在定义阶段按照从左往右的顺序依次定义的形参,称之为位置形参
# positional argument
def fn(a, b, c):
print(a, b, c)

# 位置形参可以由 位置实参 与 关键字实参 来传值
fn(10, 20, 30)
fn(a=10, b=20, c=30)
```

- 默认形参

```python
# ******默认形参在定义函数阶段就已经为某个形参赋值了,用=进行复制
def fn(a=10,b=20):
print(a, b)
'''
注意:
1.位置形参与默认形参同时存在,默认形参必须在后
def fn1(a,b,c=10,d=20):
print(a, b, c, d)
2.默认形参可以由 位置实参 与 关键字实参 来传值,还可以不用传值(采用自身默认值)
fn(20, 30)
fn(a=200, b=300)
fn(100)
fn(b=100)
3.默认参数的值在函数定义阶段就已经固定死了,只在定义阶段给赋值一次
m=10
def foo(x,y=m):
print(x,y)
m=20
foo(1)
结果1,10
4.默认参数的值通常应该是不可变类型
'''
# 位置形参必须传值,默认形参分情况传值
fn1(100, 200, d=1000)
```

- 变长位置形参

```python
# 可变长形参只能由 位置实参 来传值
def fn(a, b=10, *args):
print(a, b)
print(args)

# ******在形参中带*,会将调用函数时溢出的位置实参保存成元组的形式接受 位置形参与默认形参未接受完的 所有传入的位置实参,然后赋值*给后面的的变量名

# 小细节:可变长形参只能接受位置实参的值,位置实参还必须在关键字实参前,
# 导致默认形参只能由位置实参来传值(这是在要传入默认形参的情况下,当然也可以不用传)
fn(1, 20, 100, 200)

fn(100)

可变长位置形参整体赋值(单列集合:str,list,set,tuple)单列集合将该变量进行打散,传值(本质传递的是地址)
def fn(*args):
print(args)


fn(1, 2, 3, 4, 5) # (1, 2, 3, 4, 5)

a = 'ab'
b = [1, 2]
c = (1, 2)
d = {1, 2}
fn(a) # ('ab', )
fn(b) # ([1, 2], )
fn(c) # ((1, 2), )
fn(d) # ({1, 2}, )

# 问
# 就拿a,b,c,d进行传值,如何得到
'''
('a', 'b')
(1, 2)
'''
#*****在实参中带* ,但凡在实参中带星的,在传值前都先将其打散成位置实参,进行赋值。(单列集合(保护字符串)将该变量进行 打散 传值 (本质传递的是地址))
fn(*a)
fn(*b)
fn(*c)
fn(*d)

# 打散
def fn1(*args):
print(args)
ls = [1, 2, 3, 4, 5]
fn1(ls) # (ls, )

fn1(*ls) # 将ls打散为1,2,3,4,5再进行传值=>(1,2,3,4,5)
```

## 关键字形参

```python
# *为分割线,可以有变量名 *args, 也可以只用来做分隔
# a:位置
# b:默认
# c,e:无值关键字形参
# d:有值关键字形参

# 注:
# a和b有先后顺序
# c,d, e无先后顺序

# *****关键字形参必须由 关键字实参 来传值, 出现在*后的都是关键字形参
def tt(a, b=10, *, c, d=10, e):
print(a, b, c, d, e)

# keyword-only arguments
def fn(*, a, b=10, c):
print(a, b, c)
# fn(10, 20, 30) # 错误:TypeError: fn() takes 0 positional arguments but 3 were given
fn(b=300, c=100, a=200)


可变关键字形参
#******可变长关键字形参:会将调用函数时溢出关键字实参保存成字典的形式,然后赋值**后的变量名
# 用字典来存放数据
def fn(*, a, b=20, c, **kwargs):
print(a, b)
print(kwargs)

fn(d=40, e=50, a=10, c=30)


# *****在实参中带**,但凡在实参中带**的,在传值前都先将其打散成关键字实参,再进行赋值。
dic = {'name': 'Owen', 'age': 18}
def fn1(**kwargs):
print(kwargs)

fn1(**dic)


dd = {
'k1': [1, 2, 3, 4, 5],
'k2': {"name":"Bob"}
}
fn1(**dd)


def fn2(*args):
print(args)
ll = [1, [1, 2], {"name":"Bob"}]
fn2(*ll) # (1, [1, 2], {"name":"Bob"})
```

posted @ 2019-04-01 16:27  Tiffany'.'  阅读(137)  评论(0编辑  收藏  举报