小白IT:Python中的函数是什么样,入门?

Python 函数

函数基础

函数

函数是逻辑结构化和过程化的一种编程方法,就是一段有特定功能的代码的封装.

函数的作用
  1. 封装某一特定功能,组织代码结构
  2. 减少重复代码和冗余,提高可读性
  3. 便于扩展,管理和维护
函数的定义
def 函数名(参数1,参数2,参数3,...):
    '''注释'''
    函数体
    return 返回的值
    
函数名()
#函数名要能反映其意义

注意:函数在定义时,只检测语法,不执行代码,会将函数体加载到内存中。

函数的调用

函数调用方式:函数名+调用操作符()

  • 如果函数中带参数,调用时需要传入参数。
  • 函数需要先定义才能调用
def foo():
    print('from foo')

foo()  # 调用函数
小结

函数定义

  • def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":"。
  • def 是固定的,不能变,必须是连续的def三个字母。
  • 空格:为了将def关键字和函数名分开,必须空格(四声),当然你可以空2格、3格或者你想空多少都行,但正常人还是空1格。
  • 函数名:函数名只能包含字符串、下划线和数字且不能以数字开头。虽然函数名可以随便起,但我们给函数起名字还是要尽量简短,并能表达函数功能
  • 括号:是必须加的,先别问为啥要有括号,总之加上括号就对了!

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

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

函数的参数

到了这里,我们知道了函数如何返回结果,也就是返回值,但是能不能将计算的字符串变成可动态控制的呢,这就需要用到函数的参数来完成。

def mylen(s1): #接受传递来的 hello world 带入函数中进行计算--形式参数
    """计算s1的长度"""
    length = 0
    for i in s1:
        length = length+1
    return length

#函数调用
str_len = mylen("hello world") # hello world 传入到s1--实际参数
print('str_len : %s'%str_len) #str_len : 11
实参和形参

我们调用函数时传递的这个“hello world”被称为实际参数,因为这个是实际的要交给函数的内容,简称实参。

而定义函数时的s1,只是一个变量的名字,被称为形式参数,在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参。

形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变

实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

参数的分类

从实参角度:

  1. 位置参数:arg
  2. 动态位置参数:[1,2,3,4]
  3. 关键字参数:arg=True
  4. 动态关键字参数:{arg1:1, arg2:2…}

传参顺序:位置参数 > 动态位置参数 > 关键字参数 > 动态关键字参数

从形参角度:

  1. 位置参数:arg
  2. 动态位置参数:*args
  3. 默认参数 :arg=True
  4. 动态关键字参数:**args

接收顺序:位置参数 > 动态关键字参数 > 默认参数 > 动态关键字参数

动态位置参数

按位置传值多余的参数都由args统一接收,保存成一个元组的形式

def mysum(*args):  # 动态接受位置参数
    the_sum = 0
    for i in args:
        the_sum+=i
    return the_sum

the_sum = mysum(1,2,3,4)
print(the_sum)
动态关键字参数
def stu_info(**kwargs):  # 动态接受关键字参数
    print(kwargs)
    print(kwargs['name'],kwargs['sex'])

stu_info(name = 'alex',sex = 'male')
函数的返回值

我们使用函数,需要获得函数给我们计算的结果,像刚才的函数,我们并不能拿到返回值,因为我们并没有让函数给我们返回任何值,此时需要用到return给函数返回结果。

return关键字
  • 用来终止函数,只要遇到return,函数后面所有的语句都不再执行,无论后面有几个return,也只运行到第一个return
  • 返回函数运行的结果
def test():
    print(1)
    print(2)
    return '函数结束了'
    print(3)

test() # 函数运行,执行里面的语句
ret = test() # 用ret接收函数的返回值
print(test())
print(ret)
函数中有return
  • 返回一个值

  • 返回多个值,会放入一个元组中返回

def ret_demo1():
    '''返回多个值''' 
    return 1,2,3,4


def ret_demo2():
    '''返回多个任意类型的值'''
    return 1,['a','b'],3,4

ret1 = ret_demo1()
print(ret1)
ret2 = ret_demo2()
print(ret2)
  • 返回多个值的接收
def ret_demo2():
    return 1,['a','b'],3,4

#返回多个值,用一个变量接收
ret2 = ret_demo2()
print(ret2)

#用多个值接收返回值:返回几个值,就用几个变量接收
a,b,c,d = ret_demo2()#(1, ['a', 'b'], 3, 4)
print(a,b,c,d) #1 ['a', 'b'] 3 4
函数中没有return

函数会默认给我们返回None

#函数定义
def mylen():
    """计算s1的长度"""
    s1 = "hello world"
    length = 0
    for i in s1:
        length = length+1
    print(length)

#函数调用
str_len = mylen()
#因为没有返回值,此时的str_len为None
print('str_len : %s'%str_len)



函数进阶

函数的命名空间

从python解释器开始执行之后,就在内存中开辟了一个空间,每当遇到一个变量的时候,就把变量名和值之间的对应关系记录下来。

但是当遇到函数定义的时候解释器只是象征性的将函数名读入内存,表示知道这个函数的存在了,至于函数内部的变量和逻辑解释器根本不关心。

等执行到函数调用的时候,python解释器会再开辟另一块内存空间来存储这个函数里的代码内容,这个时候,程序才关注函数里面有哪些变量,而函数中的变量会存储在新开辟出来的内存中。函数中的变量只能在函数的内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

我们给这个“存放名字与值的关系”的空间起了一个名字——叫做命名空间。

全局命名空间和局部命名空间

代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间,在函数的运行中开辟的临时的空间叫做局部命名空间

命名空间的本质:存放名字与值的绑定关系

命名空间分类
  • 内置命名空间:python解释器整个环境,比如python解释器为我们提供的名字:input,print,str,list,tuple…它们都是我们熟悉的,拿过来就可以用的方法。
  • 内置命名空间:目前来说是一个py文件没有缩进的空间
  • 局部命名空间:python函数内部空间

在这里插入图片描述

加载顺序

内置命名空间(程序运行前加载)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:调用时才加载)

调用顺序

在局部调用:局部命名空间->全局命名空间->内置命名空间

x = 1
def f(x):
    print(x)

print(10)

在全局调用:全局命名空间->内置命名空间

x = 1
def f(x):
    print(x)

f(10)
print(x)
#10  是执行局部空间输出的数值
#1   --执行全局空间输出数值
全局变量和局部变量

全局变量**:**在程序的一开始没有缩进的地方定义的变量称为全局变量。作用域是整个程序

局部变量**:**在程序或子程序中定义的变量称为局部变量,作用域是该程序和其子程序内部

全局变量global关键字

在函数内部(局部作用域)引用全局变量,如果全局没有,则会创建一个全局变量。

  • 如果函数中有global关键字,变量本质上就是全局的那个变量,可读取可赋值。
  • 如果函数的内容无global关键字,优先读取局部变量,无法对全局变量重新赋值,但是对于可变类型,可以对内部元素进行操作
def func():
    global a # 没有全局变量a,直接定义一个全局变量a
    a = 3
func()
print(a)  # 3 打印的是定义的全局变量的a

count = 1
def search():
    global count  # 申明count是全局中的count变量
    count = 2
search()
print(count)  # 2 打印的是被改过的全局变量
局部变量nonlocal关键字

不能修改全局变量

在局部作用域中,对最近的父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。

如果整个局部作用域里面没有找到nonlocal申明的变量,则会报错。

a = 1
def func():
    a = 2
    print(a)
    def func1():
        nonlocal a  # 引用父级的变量a,此时a=2
        a += 1
        print(a)
    func1()
print(a) # 还是全局变量a
func() # 2 3 1

函数的嵌套调用

函数内部中调用函数就是函数的嵌套调用

def max1(x,y):
    m  = x if x>y else y
    return m

def max2(a,b,c,d):
    res1 = max1(a,b) # max2中调用max1函数
    print('res1',',',res1)
    res2 = max1(res1,c)
    print('res2', ',', res2)
    res3 = max1(res2,d)
    print('res3', ',', res3)
    return res3

print(max2(23,-7,31,11))
# res1 , 23
# res2 , 31
# res3 , 31
# 31
函数的嵌套定义

函数内部中定义函数就是函数的嵌套定义

def f1():
    def f2():
        def f3():
            print("in f3")
        print("in f2")
        f3()
    print("in f1")
    f2()  
f1()
in f1
in f2
in f3
函数名的使用

函数名本质上就是一个变量,指向了函数体的内存地址。

函数名的使用

可以当做变量被引用
def func():
    print('in func')

f = func
print(f)
可以被当作容器类型的元素
def f1():
    print('f1')

def f2():
    print('f2')

def f3():
    print('f3')

l = [f1,f2,f3]
d = {'f1':f1,'f2':f2,'f3':f3}
#调用
l[0]()
d['f2']()

#f1
#f2
可以当作函数的参数和返回值
# 当做参数传递
def foo():
    print('来自函数foo')

def foo1(func):
    func()

foo1(foo)

#来自函数foo
# 当做返回值返回
def foo():
    def foo1():
        print('from foo1')
    return foo1

a = foo()# 先调用foo() 函数空间里的--得到a=foo1
a()

函数闭包

什么是闭包

闭包函数:嵌套函数中内部函数包含对外部作用域而非全剧作用域变量的引用,该内部函数称为闭包函数。

函数内部定义的函数称为内部函数

实例!

def func():
    name = 'self哥'
    def inner():  # 这就是个闭包函数
        print(name)
闭包函数的意义

闭包:返回函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,使得该函数无论在何处调用,优先使用自己外层包裹的作用域。

我们都知道函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?

是不是直接就把这个函数的名字返回就好了?

这才是闭包函数最常用的用法

def func():
    name = 'self哥'
    def inner():
        print(name)
    return inner

f = func()
f()  # 返回的函数 f 附带了一层作用域,可以使用作用域中的变量
判断闭包函数的方法__closure__
#输出的__closure__有cell元素 :是闭包函数
def func():
    name = 'self哥'
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f = func()
f()

#输出的__closure__为None :不是闭包函数
#输出的(<cell at 0x107e62048: str object at 0x107ef5308>,) --是闭包函数
name = 'anni'
def func2():
    def inner():
        print(name)
    print(inner.__closure__)
    return inner

f2 = func2()
f2()

(<cell at 0x107e623d8: str object at 0x107efe138>,)
self哥
None
anni

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值