28 Mar 18 函数

一、作业讲解
注册功能升级:
#1、拿到用户输入的合法的信息:用户名、密码、余额
db_path='db.txt'
 
def get_uname():
    while True:
        uname=input('用户名>>:').strip()
        if not uname.isalpha():
            print('33[45m用户名必须为英文字母...33[0m')
            continue
        with open(r'%s' %db_path,'r',encoding='utf-8') as f:
            for line in f:
                uinfo=line.strip('
').split(',')
                if uname == uinfo[0]:
                    print('33[45m用户名已存在...33[0m')
                    break
            else:
                return uname
# uname=get_uname()
# print(uname,type(uname),uname.isalpha())
 
def get_pwd():
    while True:
        pwd1=input('请输入密码>>: ').strip()
        pwd2=input('再次输入密码>>: ').strip()
        if pwd1 == pwd2:
            return pwd1
        else:
            print('33[45m两次输入的密码不一致,请重新输入...33[0m')
 
# pwd=get_pwd()
 
def get_bal():
    while True:
        bal=input('请输入余额: ').strip()
        if bal.isdigit():
            # bal=int(bal)
            return bal
        else:
            print('33[45m钱必须是数字,傻叉...33[0m')
 
# bal=get_bal()
 
#2、写入文件
def file_hanle(uname,pwd,bal):
    with open(r'%s' %db_path,'a',encoding='utf-8') as f:
        f.write('%s,%s,%s
' %(uname,pwd,bal))
 
# file_hanle('egon','123','300','C:a
db.txt')
# file_hanle('alex','123','300',)
 
# 注册功能
def register():
    uname=get_uname() #拿到合法的用户名
    pwd=get_pwd() #拿到合法的密码
    bal=get_bal() #拿到合法的余额
    file_hanle(uname,pwd,bal) #写入文件
 
# register()
 
转账功能
db_path='db.txt'
 
#1、源账户减钱
def cal_mon(src_user,money):
    pass
 
#2、目标账户加钱
def add_mon(dst_user,money):
    pass
 
def transfer(src_user,dst_user,money):
    cal_mon(src_user,money)
    add_mon(dst_user,money)
 
transfer('egon','alex',300)
 
二、补充知识
1.     *的应用场景
def sum2(*args): #args=(1,2,3)   ##求和
    res=0
    for num in args:
        res+=num
    return res
 
print(sum2(1,2,3,4,5,6,7))
 
2.     **的应用场景
def auth(name,pwd,**kwargs):    ##考虑扩展性
    print(name)
    print(pwd)
    print(kwargs)
 
auth(name='egon',pwd='123',group='group1')
 
3.     *args 和 **kwargs最重要的应用
def index(name):
    print('welecome %s to index page' % name)
def wrapper(*args, **kwargs):
    index(*args, **kwargs)  # index(1,2,name='egon')
wrapper(1, 2, name='egon')
 
4.     引用顺序及常规调用
def foo(x,y=1,*args,z,**kwargs):  ## *号后面为命名关键字参数, 注意顺序
pass
 
def foo(x,*args,**kwargs):   ##两种常用的使用方式
    pass
 
def foo(x,y=1):            ##两种常用的使用方式
    pass
 
三、命名关键字参数
print(help(函数名)) e.g print(help(foo)) , 查看函数
def foo(x,y,*,z):
print(x,y,z)
 
命名关键字参数:在*后面参数都是命名关键字参数(格式)
特点:
1 必须被传值
1 约束函数的调用者必须按照key=value的形式传值
2 约束函数的调用者必须用我们指定的key名
 
复杂的写法:
def auth(*args,**kwargs):
    """
    使用方式auth(name="egon",pwd="123")
    :param args:
    :param kwargs:
    :return:
    """
    # print(args,kwargs)
    if len(args) !=0:
        print('必须用关键字的形式传参')
        return
    if 'name' not in kwargs:
        print('必须用指定的key名name')
        return
    if 'pwd' not in kwargs:
        print('必须用指定的key名pwd')
        return
 
    name=kwargs['name']
    pwd=kwargs['pwd']
    print(name,pwd)
 
四、函数嵌套
1、 函数的嵌套调用:在函数内又调用了其他函数
def max2(x,y):
    if x > y:
        return x
    else:
        return y
 
def max3(x,y,z):
    res1=max2(x,y)
    res2=max2(res1,z)
    return res2
 
print(max3(11,199,2))
 
2、 函数的嵌套定义:在函数内又定义其他函数
def func1():
    print('from func1')
    def func2(): #func2=内存地址
        print('from func2')
 
    print(func2) #<function func1.<locals>.func2 at 0x0000024907A098C8>
    func2()
 
func1()
 
def f1():
    print('f1')
    def f2():
        print('f2')
        def f3():
            print('f3')
        f3()
    f2()
f1()
 
五、名称空间与作用域
1、 名称空间:存放名字与值绑定关系的地方
 
2、 名称空间分为三类
a.     内置名称空间:存放python解释器自带的名字,在解释器启动时就生效,解释器关闭则实效
b.     全局名称空间:文件级别的名字,在执行文件的时候生效,在文件结束或者文件执行期间被删除则失效(del func)(不是内置,局部名称空间(函数里的))
c.      局部名称空间:存放函数内定义的名字(函数的参数以及函数内的名字都存放与局部名称空间),在函数调用时临时生效,函数结束则实效
 
   加载顺序: 内置名称空间-》全局名称空间-》局部名称空间
   查找名字: 局部名称空间-》全局名称空间-》内置名称空间
 
3. 作用域
全局作用域:包含的是内置名称空间与全局名称空间的名字
特点: 在任何位置都能够访问的到;该范围内的名字会伴随程序整个生命周期
 
局部作用域:包含的是局部名称空间的名字
特点:只能在函数内使用;调用函数时生效,调用结束失效
 
六、函数对象
函数在python中时第一类对象
1.     可以被引用
def func():
    print('from func')
f=func
 
2.     可以当作参数传入
def bar(x):
    print(x)
    x()
bar(func)
 
3.     可以当作函数的返回值
def bar(x): # x=func
    return x #return func
res=bar(func) #res=func
# print(res)
res()
 
4.     可以当作容器类型的元素
def auth():
    print('登陆。。。。。')
 
def reigster():
    print('注册。。。。。')
 
def search():
    print('查看。。。。')
 
def transfer():
    print('转账。。。。')
 
def pay():
    print('支付。。。。')
 
dic={
    '1':auth,
    '2':reigster,
    '3':search,
    '4':transfer,
    '5':pay
}
 
# print(dic)
# dic['2']()
 
def interactive():
    while True:
        print("""
        1 认证
        2 注册
        3 查看
        4 转账
        5 支付
        """)
        choice=input('>>: ').strip()
        if choice in dic:
            dic[choice]()
        else:
            print('非法操作')
 
interactive()
 
七、闭包函数
闭:指的是定义在函数内部的函数
作用域关系:在函数定义阶段就规定死了,与调用位置无关
def outter():
    x=2
    def inner():
        x=1
        print('from inner',x)
    return inner
f=outter() #f=inner
def foo():
    x=1111
    f()
 
foo()
##以上结果返回1;若x=1被注释,返回2;若x=2亦被注释,报错,x=1111不会被引用,因为它在foo的局部里。
 
闭合函数:
定义在函数内部的函数;并且该函数包含对外部函数作用域中名字的引用,该函数就成为闭包函数
def outter():
    name='egon'
    def inner():
        print('my name is %s' %name)
    return inner
f=outter()
 
为函数体传值的方式(了解)
方式一:将值以参数的形式传入
import requests
def get(url):
    response=requests.get(url)
    if response.status_code == 200:
        print(response.text)
get('https://www.baidu.com')
 
方式二:闭包函数
import requests
import time
 
def outter(url): #url='https://www.baidu.com'
 
    # url='https://www.baidu.com'
    def get():
        response=requests.get(url)
        if response.status_code == 200:
            print(response.text)
 
    return get
 
baidu=outter('https://www.baidu.com')
python=outter('https://www.python.org')
 
baidu()
print('=====================>')
time.sleep(3)
baidu()
 
 
原文地址:https://www.cnblogs.com/zhangyaqian/p/py20180328.html