Python函数

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

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

函数的返回值:

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

return返回一个值,如下:

  1. def fun():
  2. return 1 # return 数字1
  3. ret = fun()
  4. print(type(ret),ret)
  5.  
  6. 打印内容如下:
  7. <class 'int'> 1

return返回多个值,如下:

  1. def fun():
  2.   return 1,2,3,4 # return多个值
  3. ret = fun()
  4. print(type(ret),ret)
  5.  
  6. # 打印内容如下:
  7. <class 'tuple'> (1, 2, 3, 4)

函数的参数:

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

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

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

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

位置传参。如下:

  1. def max_num(num1,num2): # 返回最大的数字
  2. if num1 > num2:
  3. return num1
  4. else:
  5. return num2
  6. ret = max_num(10,20)
  7. print(ret)
  8.  
  9. 打印内容如下:
  10. 20

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

  1. def max_num(num1=0,num2=20): # 默认参数
  2. if num1 > num2:
  3. return num1
  4. else:
  5. return num2
  6. ret = max_num(num1=10) # 我们只传递num1参数
  7. print(f'最大数是:{ret}')
  8. # 打印内容如下
  9. 最大数是:20

混合传参:

  1. # 参数中有位置参数和默认参数的称为混合参数
  2. # 注意:位置参数必须放在默认参数前
  3. def max_num(num1,num2=20): # 混合传参
  4. if num1 > num2:
  5. return num1
  6. else:
  7. return num2
  8. ret = max_num(10)
  9. print(f'最大数是:{ret}')
  10. # 打印内容如下
  11. 最大数是:20

关于默认参数需要注意:

  1. def fun(val, list_1=[]): # 默认参数是可变的数据类型列表
  2. list_1.append(val)
  3. return list_1
  4.  
  5. list1 = fun(10)
  6. list2 = fun('Hello World',[]) # 给默认参数传递一个空列表
  7. list3 = fun('a')
  8. list4 = fun('b')
  9.  
  10. print("list1 = %s" % list1)
  11. print("list2 = %s" % list2)
  12. print("list3 = %s" % list3)
  13. print("list4 = %s" % list4)
  14.  
  15. # 打印内容如下
  16. list1 = [10, 'a', 'b']
  17. list2 = ['Hello World']
  18. list3 = [10, 'a', 'b']
  19. list4 = [10, 'a', 'b']

通过打印结果可以发现list1、list3、list4的结果是一样的。它们还有个共同点就是在传参的过程中没有填写默认参数,list2的默认参数因为传递了个空列表,所以结果和其它的不一样。

由此可以知道当默认参数是可变的数据类型时,如果不传递默认参数而是直接使用默认的参数时,虽然多次调用了函数,但是函数的默认参数都是引用同一块的内存地址(应该是为了节省内存),当给默认参数传递一个新值时,函数便开辟了一个新的空间给默认参数使用,所以最终list2和其它的值不一样。

函数动态参数

动态参数分为两种:动态位置参数、动态默认参数。

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

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

函数传参如:fun1("Hello",123,"World")  我们将传递多个参数的过程称为打散。

下面是错误的示范:

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

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

  1. def fun1(buf,*args): #位置参数在动态位置参数前面
  2. print(buf)
  3. print(args)
  4. return args
  5. ret = fun1("Hello",123,"World")
  6. print(type(ret))
  7.  
  8. # 打印内容如下;
  9. Hello
  10. (123, 'World')
  11. <class 'tuple'> # 动态位置参数的返回类型

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

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

  1. def fun1(s2="",**kwargs): # 默认参数必须放在动态默认参数前面
  2. print(s2)
  3. print(kwargs)
  4. return kwargs
  5. ret = fun1(s="Hello",num=123,s2="World")
  6. print(type(ret))
  7.  
  8. #打印内容如下:
  9. World
  10. {'s': 'Hello', 'num': 123}
  11. <class 'dict'> #动态默认参数返回的是一个字典
  12.  
  13. def fun(*args,**kwargs): # 万能传参
  14. print(args,kwargs)
  15. fun([1,2,3],(3,2,3),**{"电视剧":1,"电影":2}) # 字典需要打散传递给动态默认参数,如果不打散会被动态位置参数给接收了
  16.  
  17. # 打印内容太如下:
  18. ([1, 2, 3], (3, 2, 3)) {'电视剧': 1, '电影': 2}

关于def fun(*args,**kwargs)这是俗称的万能参数,可以接收任意数量的参数。我们将接收参数的过程称为聚合,而聚合的关键点在于*和**。*和**主要是将从实参传过来的多个参数进行聚合。*args将所有位置参数聚合成元组,而**kwargs将所有默认(关键字)参数聚合成字典。还有个需要注意的地方是在传参的过程如func(1,2,3,**{键:值}),在关键字参数字典中的键必须是字符串否则会报错。

总结:

形参的位置顺序:

位置参数 ==>动态位置参数==>默认参数==>动态默认参数

实参的位置顺序:

位置参数 ==>动态位置参数==>关键字参数==>动态关键字参数

名称空间

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

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

加载顺序:

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

取值顺序:

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

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

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

局部作用域:在函数内部可以使用。

作用域命名空间:

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

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

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

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

  1. def fun1():
  2. num = 10
  3. print(locals()) # 打印局部作用域中的内容
  4. fun1()
  5.  
  6. # 打印内容如下:
  7. {'num': 10}

gloabal和nonlocal

gloabal:用于在局部空间内修改全局变量,如果全局变量不存在将创建一个全局变量。只有数字和字符串需要global,list,dic,set不需要global。

  1. # 全局变量
  2. num = 20
  3. list_1 = [1,2,3]
  4.  
  5. def fun1():
  6. global num # 声明全局变量
  7. num = 10 # 修改全局变量,如果不用global声明在函数内部是不能修改全局变量的
  8.  
  9. global new_num # new_num不存在将创建成全局变量
  10. new_num = 200 # 给全局变量赋值
  11.  
  12. list_1.append(10) # 可变数据类型不需要使用global
  13.  
  14. fun1() # 调用函数
  15. print(f'num={num}')
  16. print(f'new_num={new_num}')
  17. print(f'list_1={list_1}')
  18.  
  19. # 打印内容如下
  20. num=10
  21. new_num=200
  22. list_1=[1, 2, 3, 10]

注意:在函数内创建全局变量时必须要调用这个函数才能创建全局变量,否则不能创建全局变量。

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

nonlocal特点:

1、不能修改全局变量。

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

  1. def fun1():
  2. num = 10 # 局部变量
  3. def fun2():
  4. nonlocal num 向上一层查找局部变量num
  5. num = 200 #修改局部变量num
  6. fun2()
  7. print(num) # 打印局部变量num
  8.  
  9. fun1() # 调用函数打印num最终结果
  10.  
  11. #打印内容如下:
  12. 200 # num被修改成了200

下一篇:函数名,闭包,迭代器:https://www.cnblogs.com/caesar-id/p/10311931.html

Python函数(一)之杵臼之交的更多相关文章

  1. python 函数之day3

    一 函数的语法及特性 什么是函数? 定义:函数是一个功能通过一组语句的集合,由名字(函数名)将其封装起来的代码块,要想执行这个函数,只要调用其函数名即可. 特性: 减少重复代码 使程序变的可扩展 使程 ...

  2. Python函数作用域的查找顺序

    函数作用域的LEGB顺序 1.什么是LEGB? L:local 函数内部作用域 E:enclosing 函数内部与内嵌函数之间 G:global 全局作用域 B:build-in 内置作用域 2.它们 ...

  3. Python函数讲解

    Python函数

  4. Python函数信息

    Python函数func的信息可以通过func.func_*和func.func_code来获取 一.先看看它们的应用吧: 1.获取原函数名称: 1 >>> def yes():pa ...

  5. Python函数参数默认值的陷阱和原理深究"

    本文将介绍使用mutable对象作为Python函数参数默认值潜在的危害,以及其实现原理和设计目的 本博客已经迁移至: http://cenalulu.github.io/ 本篇博文已经迁移,阅读全文 ...

  6. Python开发【第四章】:Python函数剖析

    一.Python函数剖析 1.函数的调用顺序 #!/usr/bin/env python # -*- coding:utf-8 -*- #-Author-Lian #函数错误的调用方式 def fun ...

  7. Python函数解析

    对于Python的函数,我们需要记住的是: 1. 函数的默认返回值是None. 2. python是一个自上而下逐行解释并执行的语言.因此,函数的定义必须在函数被调用之前.同名的函数,后定义的会覆盖前 ...

  8. Python入门笔记(18):Python函数(1):基础部分

    一.什么是函数.方法.过程 推荐阅读:http://www.cnblogs.com/snandy/archive/2011/08/29/2153871.html 一般程序设计语言包含两种基本的抽象:过 ...

  9. Python函数1

    Python 函数命令的使用 想想我们之前数学中学到的函数,首先我们需要定义一个函数,例如f(x)=x, 当x输入任意数的时候,f(x)都能输出和x相等的数值. 那么在Python中是如何实现的呢? ...

随机推荐

  1. Python获取文件夹的名字

    dir = "../data/20170308/221.176.64.146/" # root 文件夹下的所有文件夹(包括子文件夹)的路径名字../data/20170308/22 ...

  2. 1.Django安装与运行

    Django基本配置 Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Se ...

  3. Kafka从入门到进阶

    1.  Apache Kafka是一个分布式流平台 1.1  流平台有三个关键功能: 发布和订阅流记录,类似于一个消息队列或企业消息系统 以一种容错的持久方式存储记录流 在流记录生成的时候就处理它们 ...

  4. Nancy in .Net Core学习笔记 - 初识Nancy

    前言 去年11月份参加了青岛MVP线下活动,会上老MVP衣明志介绍了Nancy, 一直没有系统的学习一下,最近正好有空,就结合.NET Core学习总结了一下. 注: 本文中大部分内容都是对官网文档的 ...

  5. 使用 SetColorFilter 神奇地改变图片的颜色

    关键代码如下: colors.xml文件中定义一个颜色值: <color name="permission_dialog_img_color">#000000</ ...

  6. [Leetcode]538. Convert BST to Greater Tree

    Given a Binary Search Tree (BST), convert it to a Greater Tree such that every key of the original B ...

  7. Spring Boot2.0:使用Docker部署Spring Boot

    一.Spring Boot项目添加 Docker 支持1.在pom.xml中添加 Docker 构建插件 <plugins> <!-- Docker maven plugin --& ...

  8. 打造自己的.NET Core项目模板

    前言 每个人都有自己习惯的项目结构,有人的喜欢在项目里面建解决方案文件夹:有的人喜欢传统的三层命名:有的人喜欢单一,简单的项目一个csproj就搞定.. 反正就是萝卜青菜,各有所爱. 可能不同的公司对 ...

  9. 痞子衡嵌入式:ARM Cortex-M文件那些事(7)- 反汇编文件(.s/.lst/.dump)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式开发里的反汇编文件(.s, .lst, .dump). 痞子衡在第四.五.六节课分别介绍了编译器/链接器生成的3种output文件( ...

  10. Perl多线程(2):数据共享和线程安全

    线程数据共享 在介绍Perl解释器线程的时候一直强调,Perl解释器线程在被创建出来的时候,将从父线程中拷贝数据到子线程中,使得数据是线程私有的,并且数据是线程隔离的.如果真的想要在线程间共享数据,需 ...