博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python函数(一)之杵臼之交
阅读量:5243 次
发布时间:2019-06-14

本文共 4769 字,大约阅读时间需要 15 分钟。

Python函数

函数的作用:对功能进行封装,减少重复代码,方便维护,流程清晰明了,易于理解。

函数的结构:
      def 函数名():
            函数体
            return语句

函数的返回值:

  • 可以用于终止函数的运行,也可以返回一个值给调用者。
  • 如果函数不写返回值默认返回一个None。
  • 函数return可以返回任意数据类型。
  • 如果return多个值则返回的数据类型是元组。
  • 如果return一个数据,返回值是原数据类型。.

return返回一个值,如下:

def fun():    return 1       # return 数字1ret = fun()print(type(ret),ret)打印内容如下:
1

return返回多个值,如下:

def fun():  return 1,2,3,4   # return多个值ret = fun()print(type(ret),ret)# 打印内容如下:
(1, 2, 3, 4)

函数的参数:

形参:分为位置参数、默认参数、混合参数三种。
实参:分为位置参数、关键字参数、混合参数三种。

传参:指从实参到形参的传递过程。.

参数的顺序: 位置参数 > 默认参数(关键字参数),在默认参数前边写位置参数。

位置传参。如下:

def max_num(num1,num2):   # 返回最大的数字    if num1 > num2:        return num1    else:        return num2ret = max_num(10,20)print(ret)打印内容如下:20

默认参数,就是如果我们不传参数,函数执行形参中的默认参数。如下:

def max_num(num1=0,num2=2):  # 默认参数    if num1 > num2:        return num1    else:        return num2ret = max_num()    # 我们不写参数print(ret)打印内容如下:2

默认参数我们也可以传参,如下:

def max_num(num1=0,num2=2):    if num1 > num2:        return num1    else:        return num2ret = max_num(num1=10,num2=20)  # 也可以(10,20),但既然定义了默认参数,最好在传参过程中,把关键字也写上print(ret)# 打印内容如下:20

混合传参:

def max_num(num1,num2=2): # 参数中有位置参数和默认参数的称为混合参数,切记混合参数:位置参数必须放在默认参数前    if num1 > num2:        return num1    else:        return num2ret = max_num(10,num2=20)  # 传参print(ret)# 打印内容如下:20

关于默认参数的一些思考:

def extendList(val, list=[]):    list.append(val)return listlist1 = extendList(10)list2 = extendList(123,[])list3 = extendList('a')list4 = extendList('b')list5 = extendList('c')print("list1 = %s" % list1)print("list2 = %s" % list2)print("list3 = %s" % list3)print("list4 = %s" % list3)print("list5 = %s" % list3)# 打印内容如下:list1 = [10, 'a', 'b', 'c'] list2 = [123] list3 = [10, 'a', 'b', 'c'] list4 = [10, 'a', 'b', 'c'] list5 = [10, 'a', 'b', 'c']

通过打印结果可以发现list1、list3、list4、list5它们最终的结果是一样的。它们还有个共同点就是在传参的过程中没有填写默认参数,list2的默认参数因为传递了个空列表,所以结果和其它的不一样。由此可以总结:当省略默认参数时,虽然多次调用了函数,但是函数都是引用同一块的默认参数地址(应该是为了节省内存),当给默认参数传值的时候,函数开辟了一个新的空间给默认参数使用。

函数参数,动态参数。

动态参数分为两种:动态位置参数、动态默认参数。
动态位置参数:动态位置参数会接收所有位置参数,所以要想既使用位置参数又使用动态位置参数,一定要将位置参数放在动态位置参数前面。动态位置参数用return返回的是一个元组,动态位置参数约定俗成使用*args。

在定义形参如:def fun1(*args) 我们将*args定义形参的过程称作聚合,也就是将实参中的多个参数进行聚合。
调用函数传参如:fun1("Hello",123,"World")  我们将传递多个参数的过程称为打散。
下面是错误的示范:

def fun1(*args,buf):   # 动态位置参数在位置参数前,错误    print(buf)    print(args)    return argsfun1("Hello",123,"World")# 打印内容如下:TypeError: fun1() missing 1 required keyword-only argument: 'buf'

原因在于动态位置参数会接收所有的参数,导致后面的位置参数无法接收参数导致报错。

下面是正确的写法:

def fun1(buf,*args): #位置参数在动态位置参数前面    print(buf)    print(args)    return argsret = fun1("Hello",123,"World")print(type(ret)) # 打印内容如下;Hello (123, 'World') 
# 动态位置参数的返回类型

但是一般如果用动态位置参数,就很少用位置参数了,上面这种情况一般也只是在特殊情况下会用到。从上面的结果可以得出结论:位置参数必须在动态位置参数前。

动态默认参数:会接收所有默认参数,如果形参中有默认参数,默认参数必须放在动态默认参数前面,动态默认参数用return返回一个字典。动态默认参数约定俗成的使用**kwargs。

def fun1(s2="1",**kwargs): # 默认参数必须放在动态默认参数前面    print(s2)    print(kwargs)    return kwargsret = fun1(s="Hello",num=123,s2="World")print(type(ret))#打印内容如下:World {
's': 'Hello', 'num': 123}
#动态默认参数返回的是一个字典 def fun(*args,**kwargs): # 万能传参 print(args,kwargs)fun([1,2,3],(3,2,3),**{
"电视剧":1,"电影":2}) # 字典需要打散传递给动态默认参数,如果不打散会被动态位置参数给接收了# 打印内容太如下:([1, 2, 3], (3, 2, 3)) {
'电视剧': 1, '电影': 2}

在定义形参如:def fun1(**kwargs)我们将**kwargs定义形参的过程称作聚合,也就是将实参中的多个关键字参数进行聚合。

调用函数传参如::un1(s="Hello",num=123,s2="World") 我们将传递多个参数的过程称为打散,如果有字典,使用**dict打散。
小结:形参的位置参数顺序,位置参数 ==>动态位置参数==>默认参数==>动态默认参数。

名称空间
在python解释器开始执行之后,就会在内存中开辟一个空间,每当遇到一个变量的时候,就把变量名和值之间的关系记录下来,当遇到函数定义的时候,解释器只是把函数名读入内存,表示这个函数存在了,至于函数内部的变量和逻辑,解释器是不关心的。函数只是加载进来,只有当函数被调用和访问的时候,解释器才会根据函数内部声明的变量来进行开辟变量的内部空间,随着函数执行完毕,这些函数内部变量占用的空间也会随着函数执行完毕而被清空。 
命名空间分类:

  • 内置命名空间:存放python解释器为我们提供的名字、list、tuple、str、int这些都是内置命名空间。
  • 全局命名空间:我们直接在py文件中,函数外声明的变量都属于全局命名空间。
  • 局部命名空间:在函数中声明的变量会放在局部命名空间。

加载顺序:

  1. 内置命名空间
  2. 全局命名空间
  3. 局部命名空间(函数被执行的时候)

取值顺序:

  1. 局部命名空间
  2. 全局命名空间
  3. 内置命名空间

作用域:作用域就是作用范围, 按照生效范围来看分为全局作用域和局部作用域。   

全局作用域:包含内置命名空间和全局命名空间。在整个文件的任何位置都可以使用(遵循 从上到下逐步执行)。
局部作用域:在函数内部可以使用。
作用域命名空间:

  1. 全局作用域:全局命名空间 + 内置命名空间。
  2. 局部作用域:局部命名空间。

可以使用globals()函数来查看全局作用域中的内容:

num = 10print(globals()) # 打印全局作用域的内容# 打印部分内容如下:'__cached__': None, 'num': 10}

使用locals()函数来查看局部变量:

def fun1():num = 10print(locals()) # 打印局部作用域中的内容fun1()# 打印内容如下:{
'num': 10}

gloabal和nonlocal

gloabal:用于在局部空间内修改全局变量,如果全局变量不存在将创建一个全局变量。

def fun1():    global num # 声明全局变量    num = 10 # 修改全局变量,如果不用global声明在函数内部是不能修改全局变量的            global new_num # 创建全局变量    new_num = 200 # 给全局变量赋值num = 20 # 全局变量fun1() # 调用函数print(num,new_num)# 打印内容如下:10 200

nonlocal:必须在嵌套函数内,修改离它最近的那一层的局部变量,如果上一级不存在,继续向上一层找,一直到函数的最外层停止查找,找不到会报错。

def fun1():    num = 10 # 局部变量    def fun2():        nonlocal num 向上一层查找局部变量num        num = 200 #修改局部变量num    fun2()    print(num) # 打印局部变量numfun1()        # 调用函数打印num最终结果#打印内容如下:200   # num被修改成了200

 

转载于:https://www.cnblogs.com/caesar-id/p/10291376.html

你可能感兴趣的文章
UVA 10976 - Fractions Again?!
查看>>
Dreamweaver cc新版本css单行显示
查看>>
【android】安卓的权限提示及版本相关
查看>>
JavaScript可否多线程? 深入理解JavaScript定时机制
查看>>
IOS基础学习
查看>>
PHP 导出 Excell
查看>>
Java基础教程——网络基础知识
查看>>
Kruskal基础最小生成树
查看>>
浅谈算法和数据结构: 一 栈和队列
查看>>
Java内部类详解
查看>>
【hdu 1429】胜利大逃亡(续)
查看>>
图论-次短路求法
查看>>
What's New for Visual C# 6.0
查看>>
ExtJs学习笔记之ComboBox组件
查看>>
关于收费软件
查看>>
getopt_long
查看>>
TensorFlow MNIST CNN 代码
查看>>
javascript之Style物
查看>>
JSON跨域解决方案收集
查看>>
SSH框架整合总结
查看>>