3、函数

s1 = 'helloworld'

def my_len(s):   #def定义一个函数的名字叫做my_len.传了一个参数s、函数名不能是关键字、不能已数字开头
    sum = 0
    for i in s:     #s为参数的位置
        sum += 1
    return sum      #返回sum的值

print(my_len(s1))   #调用函数并把s1传入函数中

返回值的三种情况:
1、没有返回值
2、返回一个值
可以返回任何数据类型
只要返回了,就可以接收到
如果在一个程序中有多个return,只执行第一个,后边的都不执行
3、返回多个值
返回多个值需要多少个变量去接收,多少个返回值就有多少个变量,多了不行,少了也不行
可以用一个变量去接收,变量的接收值为一个元祖

1、没有返回值
不写return
def func():
    l = ['金老板','二哥']
    for i in l:
        print(i)
print(func())

只写return
def func():
    l = ['金老板','二哥']
    for i in l:
        print(i)
    return   #函数中只要执行了return,则后边的所有操作都不执行
print(func())


返回一个值
def func1():
    return {'k','v'}
print(func1())


返回多个值
def func2():
    return 1,2
r1,r2 = func2()
print(r1,r2)


参数
没有参数,括号里不写任何数据
一个餐宿
多个参数
位置参数(有多少个参数,函数调用的时候就必须多少个元素,且必须按照参数的顺序来写)
按照关键字传参
def my_sum(a,b):
    print(a,b)
    res = a+b
    return res

站在实参的角度上:
ret = my_sum(2,1)   #按位置传参
ret = my_sum(b=1,a=2)  #按照关键字传参
ret = my_sum(1,b=2)   #可以混着用,但先必须按照位置传参,再按照关键字传参,不能给同一个变量传多个值
print(ret)


站在形参的角度上:
位置参数:必须传(多传少传都不行)
默认参数:可以不传的参数,如果不传就使用默认的参数,如果穿了就是用传的
动态参数有两种:(可以接受任意个参数)
*args :接收的是按照位置传参的值,组织成一个元祖
**kwargs : 接收的是按照关键字传参的值,组织成一个字典

def classmate(name,sex=''):  #默认参数
    print('{}:{}'.format(name,sex))
classmate('二哥','')
classmate('春哥')
classmate('张三','')

def sum1(*args): #动态参数
    n = 0
    for i in args:
        n += i
    return n
print(sum1(1,2,3,4))


函数进阶
a = 1
def func():
    print(a)
func()

命名空间和作用域

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

在局部:可以使用全局命名空间中的名字、也可以使用内置命名空间的名字
在全局:可以使用内置命名空间中的名字、不能使用局部命名空间中的名字
在内置:不能使用全局和局部的名字

在正常情况下,直接使用内置的名字
当我们在全局定义了和内置命名空间中一样的名字,我们调用是会使用全局的名字
当我自己有的时候,我就不找我的上级要了
如果自己没有就找上级要

def input():
    print('in input now')
def func():
    input()    #调用的全局命名空间中自己定义的input函数
func()


作用域有两种
全局作用域------作用在全局(包含内置和全局名字空间都属于全局作用域)---globals()
局部作用域------作用在局部-(函数)局部名字空间中的名字属于局部作用域--locals()

对于不可变数据类型,在局部可是查看全局作用域中的变量
但是不能直接修改
如果想要修改,需要再函数的一开始添加global声明,那么这个变量在局部的所有操作将对全局的变量生效

a = 1
def func():
    global a   #
    a = 2
func()
print(a)   #此刻a=2

a = 1
b = 2
def fun():
    x='aaaa'
    y='bbbbb'
    print(locals())
    print(globals())
fun()
print(globals())
print(locals())

关于globals 永远打印全局的名字
locals输出什么根据locals所在的位置,在全局 就输出全局,在局部就输出局部


函数嵌套:在函数体了去调用宁外一个函数,则叫函数嵌套
实例:比较三个数的大小
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,5,2))


函数的嵌套定义:
内部函数可以使用外部函数的变量
a = 1
def outer():
    a = 1
    def inner():
        b = 2
        print(a)
        print('inner')
        def inner2():
            nonlocal a   #nonlocal   声明了一个上层局部变量
            a += 1
            print(b)
            print('inner2')
        inner2()
    inner()
    print('局部的a:', a)
outer()
print('全局的a',a)


nonlocal 只能用于局部变量,找上层中离当前函数最近一层的局部变量


def func():
    print('123')
func()  #函数名就是内存地址
func2 =func   #函数名可以复制
func2()

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


def func():
    print(123)
def wahaha(f):
    f()
    return f       #函数名可以作为函数的返回值
q = wahaha(func)    #函数名可以作为函数的参数
print(q())



闭包
闭包一定是嵌套函数,切内部函数调用外部函数的变量
def outer():
    a = 1
    def inner():    #在这里inner就为一个闭包
        print(a)
    print(inner.__closure__)#打印某函数的closure,结果里边有cell,则该函数是一个闭包
outer()

import  urllib   #导入模块(一个Python文件)
from  urllib.request import urlopen
# ret = urlopen('http://www.xiaohuar.com/').read()
# print(ret)
#用闭包
def get_url():
    url = 'http://www.xiaohuar.com/'
    def get():
        ret = urlopen(url).read()
        print(ret)
    return get

get_func = get_url()
get_func()
原文地址:https://www.cnblogs.com/hackerlin/p/10820573.html