Python函数

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

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

函数的返回值:

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

return返回一个值,如下:

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

return返回多个值,如下:

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

函数的参数:

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

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

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

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

位置传参。如下:

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

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

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

混合传参:

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

关于默认参数需要注意:

def fun(val, list_1=[]):  # 默认参数是可变的数据类型列表
list_1.append(val)
return list_1 list1 = fun(10)
list2 = fun('Hello World',[]) # 给默认参数传递一个空列表
list3 = fun('a')
list4 = fun('b') print("list1 = %s" % list1)
print("list2 = %s" % list2)
print("list3 = %s" % list3)
print("list4 = %s" % list4) # 打印内容如下
list1 = [10, 'a', 'b']
list2 = ['Hello World']
list3 = [10, 'a', 'b']
list4 = [10, 'a', 'b']

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

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

函数动态参数

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

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

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

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

下面是错误的示范:

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

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

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

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

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

def fun1(s2="",**kwargs): # 默认参数必须放在动态默认参数前面
print(s2)
print(kwargs)
return kwargs
ret = fun1(s="Hello",num=123,s2="World")
print(type(ret)) #打印内容如下:
World
{'s': 'Hello', 'num': 123}
<class 'dict'> #动态默认参数返回的是一个字典 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 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()函数来查看全局作用域中的内容:

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

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

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

gloabal和nonlocal

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

# 全局变量
num = 20
list_1 = [1,2,3] def fun1():
global num # 声明全局变量
num = 10 # 修改全局变量,如果不用global声明在函数内部是不能修改全局变量的 global new_num # new_num不存在将创建成全局变量
new_num = 200 # 给全局变量赋值 list_1.append(10) # 可变数据类型不需要使用global fun1() # 调用函数
print(f'num={num}')
print(f'new_num={new_num}')
print(f'list_1={list_1}') # 打印内容如下
num=10
new_num=200
list_1=[1, 2, 3, 10]

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

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

nonlocal特点:

1、不能修改全局变量。

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

def fun1():
num = 10 # 局部变量
def fun2():
nonlocal num 向上一层查找局部变量num
num = 200 #修改局部变量num
fun2()
print(num) # 打印局部变量num fun1() # 调用函数打印num最终结果 #打印内容如下:
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. VIVO 手机重力传感器踩坑记录

    手上的 vivo-x9 手机传感器模式下的旋转效果有误,经查发现是 Gravity sensor 返回的数据有误,和其他机型返回的数据相反的. 参考 Gravity 的说明: A three dime ...

  2. iOS学习——图片压缩到指定大小以内

    一.图片压缩简述 在我们开发过程中,有可能会遇到拍照.或者从相册中选择图片,要么单选或者多选,然后上传图片到服务器,一般情况下一张图片可能3-4M,如果类似微信朋友圈上传9张图片大约是 35M左右,如 ...

  3. Java面试题中的Redis大合集,所有你想找的都在这里!

    概述 Redis 是一个开源的,基于内存的结构化数据存储媒介,可以作为数据库.缓存服务或消息服务使用.``` Redis 支持多种数据结构,包括字符串.哈希表.链表.集合.有序集合.位图.Hyperl ...

  4. Event(事件)的传播与冒泡

    特性说明和原理图: 标准浏览器和Ie9+浏览器都支持事件的冒泡和捕获,而IE8-浏览器只支持冒泡 标准和Ie9+浏览器用stopPropagation()或cancelBubble阻止事件传播,而ie ...

  5. 使用ML.NET实现情感分析[新手篇]后补

    在<使用ML.NET实现情感分析[新手篇]>完成后,有热心的朋友建议说,为何例子不用中文的呢,其实大家是需要知道怎么预处理中文的数据集的.想想确实有道理,于是略微调整一些代码,权作示范. ...

  6. Linux学习笔记(一):常用命令(1)

    经过统计Linux中能够识别的命令超过3000种,当然常用的命令就远远没有这么多了,按照我的习惯,我把已经学过的Linux常用命令做了以下几个方面的分割: 1.文件处理命令 2.文件搜索命令 3.帮助 ...

  7. hibernate易混淆点

    萌新小笔记: 用过hibernate的小伙伴肯定经常看到这几个东西吧!但是初学者常常会把这几个搞不清楚:dataSource,session,sessionFactory(dataSource),hi ...

  8. RabbitMQ消息队列(三)-Centos7下安装RabbitMQ3.6.1

    如果你看过前两章对RabbitMQ已经有了一定了解,现在已经摩拳擦掌,来吧动手吧! 用什么系统 本文使用的是Centos7,为了保证对linux不太熟悉的伙伴也能轻松上手(避免折在安装的路上),下面是 ...

  9. 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes

    前言 在之前的一篇文章中,我们介绍了 如何将一个本地的 Java 应用程序直接部署到阿里云 ECS ,有不少读者反馈,如果目前已经在使用阿里云容器服务 Kubernetes 了,那该如何配合这个插件部 ...

  10. Docker搭建MongoDB

    1. Docker搭建Mongodb 1.1 获取docker镜像 docker pull mongo 1.2 创建mongodb容器 docker run --name my-mongo -p 27 ...