python基础 函数

函数

定义:def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":"。

   def 是固定的,不能变

   函数名:函数名只能包含字符串、下划线和数字且不能以数字开头。虽然函数名可以随便起,但我们给函数起名字还是要尽量简短,并能表达函数功能

   括号:是必须加的  

注释:每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面第一行。以增强代码的可读性。

调用:就是 函数名() 要记得加上括号

#func  --> 函数的内存地址
#函数名() 函数的调用
#函数的内存地址() 函数的调用

函数的返回值

#返回值的3种情况
  # 没有返回值 —— 返回None
        # 不写return ---->  会默认返回一个None
        # 只写return:结束一个函数的继续 ------>会返回None
        # return None  —— 不常用
    # 返回1个值
        # 可以返回任何数据类型
        # 只要返回就可以接收到
        # 如果在一个程序中有多个return,那么只执行第一个
    # 返回多个值
        # 用多个变量接收:有多少返回值就用多少变量接收
        # 用一个变量接收: 得到的是一个元组(#python中把用逗号分割的多个值就认为是一个元组。)

函数的参数

参数可以传递多个,多个参数之间用逗号分割。

#参数
#没有参数
#定义函数和调用函数时括号里都不写内容
#有一个参数
#传什么就是什么
#有多个参数
#位置参数
#站在实参的角度上:
def classmate(name,sex):
print('%s : %s'%(name,sex))
  #按照位置传参
  classmate('二哥','男')
  #按照关键字传参
  classmate(sex='男',name = '二哥')
  #混着用可以:但是 必须先按照位置传参,再按照关键字传参数 
  #不能给同一个变量传多个值
  classmate('二哥',sex = '男')

#站在形参的角度上
  def classmate(name,sex='男'):
  print('%s : %s'%(name,sex))
    #位置参数:必须传,且有几个参数就传几个值
#默认参数: 可以不传,如果不传就是用默认的参数,如果传了就用传的
  classmate('二哥')
  classmate('朗哥',sex= '女')
#只有调用函数的时候
    #按照位置传 : 直接写参数的值
    #按照关键字 :  关键字 = 值

#定义函数的时候:
    #位置参数 : 直接定义参数
    #默认参数,关键字参数 :参数名 = '默认的值'
    #动态参数 : 可以接受任意多个参数
                #参数名之前加*,习惯参数名args,接收的是按照位置传参的值,组织成一个元组
                #参数名之前加**,习惯参数名kwargs(参数名 = '默认的值')接受的是按照关键字传参的值,组织成一个字典
def sum(*args):
    n = 0
    for i in args:
        n+=i
    return n

print(sum(1,2))
print(sum(1,2,3))
print(sum(1,2,3,4))

def func(**kwargs):
    print(kwargs)

func(a = 1,b = 2,c =3)
func(a = 1,b = 2)
func(a = 1)
例子
    #顺序:位置参数,*args,默认参数,**kwargs
def func(*args,default = 1,**kwargs):
    print(args,defaut,kwargs)

func(1,2,3,4,5,default =2,a = 'aaaa',b = 'bbbb',)

#(1, 2, 3, 4, 5) 2 {'b': 'bbbb', 'a': 'aaaa'}
例子
函数的注释
def func():
    '''
    这个函数实现了什么功能
    参数1:
    参数2:
    :return: 是字符串或者列表的长度
    '''
    pass
函数的注释
动态参数的另一种传参方式
def func(*args):
#站在形参的角度上,给变量加上*,就是组合所有传来的值。
    print(args)
func(1,2,3,4,5) #(1, 2, 3, 4, 5)
l = [1,2,3,4,5]
func(*l)  
#站在实参的角度上,给一个序列加上*,就是将这个序列按照顺序打散
# (1, 2, 3, 4, 5)
def func(**kwargs):
    print(kwargs)
func(a=1,b=2) #{'b': 2, 'a': 1}
d = {'a':1,'b':2} #定义一个字典d
func(**d) #  {'b': 2, 'a': 1}

默认参数的陷阱

# 如果默认参数的值是一个可变数据类型,
# 那么每一次调用函数的时候,
# 如果不传值就公用这个数据类型的资源
def qqxing(k,l = {}):
    l.append(1)
    l[k] = 'v'
    print(l)

qqxing(1)     #[1]
qqxing(2)     #[1,1]
qqxing(3)     #[1,1,1]

函数的命名空间(三种)

#内置命名空间 —— python解释器
# 就是python解释器一启动就可以使用的名字存储在内置命名空间中
# 内置的名字在启动解释器的时候被加载进内存里
#全局命名空间 —— 我们写的代码但不是函数中的代码
# 是在程序从上到下被执行的过程中依次加载进内存的
# 放置了我们设置的所有变量名和函数名
#局部命名空间 —— 函数
# 就是函数内部定义的名字
# 当调用函数的时候 才会产生这个名称空间 随着函数执行的结束 这个命名空间就又消失了
#在局部:可以使用全局、内置命名空间中的名字
#在全局:可以使用内置命名空间中的名字,但是不能用局部中名字
#在内置:不能使用局部和全局的名字的
#在正常情况下,直接使用内置的名字
#当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字
#当我自己有的时候 我就不找我的上级要了
#如果自己没有 就找上一级要 上一级没有再找上一级 如果内置的名字空间都没有 就报错
# 多个函数应该拥有多个独立的局部名字空间,不互相共享
倒置依赖性原则

globals()    locals()

# 作用域两种
# 全局作用域 —— 作用在全局 —— 内置和全局名字空间中的名字都属于全局作用域  ——globals()
# 局部作用域 —— 作用在局部 —— 函数(局部名字空间中的名字属于局部作用域) ——locals()
#globals 永远打印全局的名字
#locals 输出什么 根据locals所在的位置

global a

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

 函数的嵌套

#函数的嵌套定义
#内部函数可以使用外部函数的变量
nonlocal
#nonlocal 只能用于局部变量 找上层中离当前函数最近一层的局部变量
#声明了nonlocal的内部函数的变量修改会影响到 离当前函数最近一层的局部变量
# 对全局无效
# 对局部 也只是对 最近的 一层 有影响
a = 1
def outer():
    a = 1
    def inner():
        a = 2
        def inner2():
            nonlocal a  #声明了一个上面第一层局部变量
            a += 1   #不可变数据类型的修改
        inner2()
        print('##a## : ', a)
    inner()
    print('**a** : ',a)
outer()
print('全局 :',a)

##a## :  3
**a** :  1
全局 : 1

函数名的本质

def func():
    print(123)

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

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

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

sdggsf

原文地址:https://www.cnblogs.com/olivia2018/p/8119890.html