函数

 
函数
可读性强 复用性强
def 函数名():
函数体
return 返回值
函数名() 调用函数不接受返回值; 函数名就是函数的内存地址,加上括号就等于调用了
返回值 = 函数名() # 接受返回值
所有的函数 只定义不调用就一定不执行
要先定义后调用
# 定义函数
 def mylen(s):  # 定义一个函数 在这里s是形参
     n = 0
     for i in s:
         n += 1
     return n    # 返回值
 mylen()  #  调用函数
 print(mylen('dfgsdf'))   # 这里里面的值是实参
 

'''
返回值 #
没有返回值:默认返回None
    不写return 函数内的代码执行完毕自动结束
    只写return 结束一个函数
    或 return None
可以返回一个值:结束了函数且返回一个值,可以是任意的值
    return value
可以返回多个值:多个值之间用逗号隔开,接受的时候可以用一个变量接受(元祖),也可以用等量的多个变量接收
    return ...
参数

形参:定义函数的时候
  实参:调用函数的时候
    没有参数
定义和调用的时候括号里不写内容
有一个参数
传什么就是什么
有多个参数
   站在实参角度
按照位置传参
按照关键字传参
混着传参 位置传参>关键字传参
不能给同一个参数传多个值
站在形参
位置传参:必须传,且有几个参数就传几个值
默认参数:可以不传,就用默认的,如果传了实参,就用实参
动态参数:可以任意接受多个参数
参数名前加* , 习惯参数名*args :接受的是按照位置传参的值,组织成一个元祖
全部不知多少的关键字传参:**kwargs :接受的是按照关键字传参的值,组织成一个字典
def func(*args,**kwargs) 既可以接受位置又可以关键字 ,顺序不可互换
顺序: 位置参数 > *args > 默认参数 > **kwargs
def func(*args):   # 站在形参的角度上,给变量加上*,就是组合所有传来的值
    print(args)

l = [1,2,3,4,5]
func(*l)  # 站在实参的角度上,给一个序列加上*,就是将这个序列按照顺序分各个元素

def func2(**kwargs):
    print(kwargs)

d = {'a':1,"b":2}
func2(**d)  # 同样 **d


# 函数的注释
def func():
    '''
    这个函数实现了什么功能
    参数1:
    参数2:
    return:是字符串或者列表的长度
    '''
    pass
# 默认陷阱
def fun(l = []):   # 当参数是个可变数据类型,那么每一次调用函数的时候,如果不传值就公用这个数据类型的资源
    l.append()
    print(l)
命名空间



内置命名空间:python解释器
就是python解释器启动就可以使用的名字储存空间
内置的名字在启动解释器的时候被加载进内存里
eg:print()
全局命名空间:我们写的代码但不是函数中的代码
是在程序从上到下被执行的过程中依次加载进内存的
放置了我们设置的所有变量名和函数名
局部命名空间:函数
就是函数内部定义的名字
当调用函数的时候 才会产生这个名称空间,随着函数执行结束,这个命名空间就又消失了

在局部:可以使用全局,内置
在全局:可以使用内置 但不能使用局部
在内置:不能使用全局和局部
依赖倒置原则

在正常情况下,直接使用内置的名字
当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字
如果没有就找上一级要,上级没有在找上一级要,如果内置的名字空间都没有,就会报错
多个函数应该拥有多个独立的局部名字空间,不互相共享

作用域
全局作用域 -->内置和全局名字空间中的名字都属于全局作用域 -- globals()查看
局部作用域 -->函数 局部命名空间中的名字属于局部作用域 -- locals()查看
a = 1   # 这个定义在全局
def func():
    global a
    a += 1
    
print(a)
print(globals()) # 永远打印全局的名字
print(locals())  # 本地的  输出什么 根据locals所在的位置

对于不可变数据类型 在局部可查看局部作用域中的变量,但不能直接修改
如果想要修改 需要在程序的一一开始添加global声明 谨慎使用会让 代码不安全
如果在一个局部内声明一个global变量,那么这个变量在局部的所有操作将对全局的变量有效
nonlocal 只能用于局部变量 找上层中离当前函数最近一层的局部变量

def max(a,b):
    return a if a>b else b

def the_max(x,y,z):  # 函数嵌套调用
    c = max(x,y)
    return max(c,z)

print(the_max(1,2,3))
# 函数嵌套定义
# 内部函数可以使用外部函数变量
def outer():
    a = 1
    def inner():
        b = 2
        print(a)
        def inner1():

            nonlocal a # 声明了一个上层局部的第一个变量
            a = a+1
            print(b)
        inner1()
    print(a)
    inner()
outer()
def func():
    print(123)

# func() # 函数名就是内存地址
func2 = func  # 函数名可以赋值
func2()

l = [func,func2] # 函数名可以作为容器类型的元素
print(l)
for i in l:
    i()

def hel(f):
    f()
    return f   # 函数名可以作为函数的返回值
hel(func)  # 函数名可以作为函数的参数
v = hel(func)
v()
# 闭包 :嵌套函数,内部函数调用外部函数的变量
def outer():
    a = 1
    def inner():
        print(a)
    print(inner.__closure__)
    return inner  # 我返回这个函数值
outer()
print(outer.__closure__)

inn = outer() # 全局的变量指向了一个内部函数地址
inn()  # 在一个函数外部调用里面函数 延长了 a=1 的生存空间

#>> (<cell at 0x000002AE11EA1888: int object at 0x00007FF9FC5CE350>,)  只要cell什么 证明就是闭包
#>> None  不是闭包


import urllib
from urllib.request import urlopen


def get_url():
    url = 'https://www.douban.com/'
    def get():
        ret = urlopen(url)
        print(ret)
    return get
hai = get_url()
hai()

 几道题

1、写函数,检查获取传入列表或元祖对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者

def func(l):
    return l[1::2] # 切片

2.写函数 判断用户传入的值(字符串、列表、元祖)长度是否大于5

def funlen(x):
    return len(x)>5

3.写函数 检查传入列表的长度,如果大于2那边仅保留前两个长度的内容,并将新内容返回给调用者

def lentwo(l):
    if len(l)>2:
        return l[:2]

4.写函数 计算传入字符串中数字、字母、空格、以及、其他的个数,并返回结果

def er(s):
    dic = {'num':0,'alpha':0,'space':0,'other':0}
    for i in s:
        if i.isdigit():
            dic['num']+=1
        elif i.isalpha():
            dic['alpha']+=1
        elif i.isspace():
            dic['space']+=1
        else:
            dic['other']+=1
    return dic
print(er('jsdhfjs lksjdf654654 ds-0='))

5.写函数,检查用户传入的对象(字符串、列表、元祖)的每一个元素是否含有空内容,并返回结果

def ou(x):
    if type(x) is str and x:  # 参数是字符串
        for i in x:
            if i == ' ':
                return True
    elif x and type(x) is list or type(x) is tuple:  # 参数是列表或者元祖
        for i in x:
            if not i:
                return True
    elif not x:      # 直接就是空了
        return True
print(ou(''))

6.写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者

die = {'k1':'vlvl','k2':[11,22,33,44]}  # 字典中的value只能是字符串或列表
def di(dic):
    for k in dic:
        if len(dic[k])>2:
            dic[k] = dic[k][:2]
    return dic
print(di(die))

7.写函数,接受两个数字参数,返回比较大的那个数字

def mymax(a,b):
    return a if a>b else b  # 三元运算
print(mymax(3,3))
#三运运算
# 条件返回True的结果 if 条件 else 条件返回False的结果
# 必须要有结果
# 必须要有if和else
# 只能是简单的情况

8.写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整改文件的批量修改操作(进阶)(文件名要输入绝对路径)

def file(filename,old,new):
    with open(filename,encoding='utf-8',) as f,
        open('%s.bak'%filename,'w',encoding='utf-8') as f1:
        for i in f:
            if old in i:
                i = i.replace(old,new)
            f1.write(i)
    import os
    os.remove(filename)
    os.rename('%s.bak'%filename,filename)

参考:http://www.cnblogs.com/Eva-J/articles/7125925.html

原文地址:https://www.cnblogs.com/niunai/p/10524750.html