Python基础—初识函数(二)
1、给函数参数增加元信息
写好一个函数,然后想为这个函数的参数增加一些额外的信息,这样的话其他使用者就能清楚的知道这个函数应该怎么使用。
使用函数参数注解是一个很好的办法,它能提示程序员应该怎样正确使用这个函数。 例如,下面有一个被注解了的函数:
def add(x:int, y:int) -> int:
return x + y
python解释器不会对这些注解添加任何的语义。它们不会被类型检查,运行时跟没有加注解之前的效果也没有任何差距。 然而,对于那些阅读源码的人来讲就很有帮助啦。第三方
工具和框架可能会对这些注解添加语义。同时它们也会出现在文档中。
help(add) Help on function add in module __main__: add(x: int, y: int) -> int
尽管可以使用任意类型的对象给函数添加注解(例如数字,字符串,对象实例等等),不过通常来讲使用类或者字符串会比较好点。
函数注解只存储在函数的 __annotations__ 属性中。例如:
add.__annotations__
{'x': int, 'y': int, 'return': int}
注解的使用方法可能有很多种,但是它们的主要用途还是文档。 因为python并没有类型声明,通常来讲仅仅通过阅读源码很难知道应该传递什么样的参数给这个函数。 这时候
使用注解就能给程序员更多的提示,从而可以正确的使用函数。
2、有默认参数的函数
定义一个有可选参数的函数是非常简单的,直接在函数定义中给参数指定一个默认值,并放到参数列表最后就行了。
如果默认参数是一个可修改的容器,比如一个列表、集合或者字典,可以使用None作为默认值,就像下面这样:
# 使用一个列表作为默认值
def spam(a, b=None):
if b is None:
b = []
...
如果并不想提供一个默认值,而是想仅仅测试下某个默认参数是不是有传递进来,可以像下面这样写:
_no_value = object() def spam(a, b=_no_value):
if b is _no_value:
print('No b value supplied')
...
我们测试下这个函数:
spam(1) >> No b value supplied
spam(1,2) >> a=1,b=2
spam(1,None) >> a=1, b=None # 可以发现到传递一个None值和不传值两种情况是有差别的
注意:默认参数的值仅仅在函数创建的时候赋值一次。
x = 20
def spam(a,b=x):
print(a,b) spam(1) >> 1,20 x = 30
spam(1) >> 1,20
当我们改变x的值的时候对默认参数值并没有影响,这是因为在函数定义的时候就已经确定了它的默认值了。
其次,默认参数的值应该是不可变的对象,比如None、True、False、数字或字符串。 特别的,千万不要像下面这样写代码:
def spam(a,[]):
pass
如果这么做了,当默认值在其他地方被修改后将会遇到各种麻烦。这些修改会影响到下次调用这个函数时的默认值。比如:
def spam(a,b=[])
print(b)
return b x = spam(1) >> [] x.append(10) x = spam(1) >>[10]
这种结果不是我们想要的,为了避免这种结果的发生,尽量将默认值设为None,然后在函数里检查它,前面的例子就是这么做的,在测试None值时,is操作符很重要,也是这种操作的关键点,我们时常会写成下面的形式:
def spam(a, b=None):
if not b:
b=[]
这么写的问题在于尽管None值确实是被当成False, 但是还有其他的对象(比如长度为0的字符串、列表、元组、字典等)都会被当做False。 因此,上面的代码会误将一些其他输入也当成是没有输入。比如:
spam(1) # OK
x = []
spam(1, x) # 和上面一样,参数可以随意改变
spam(1, 0) # 数字,不可变类型
spam(1, '') # 字符串,不可变类型
3、匿名函数捕获变量值
先看下面代码效果:
x = 10
a = lambda y : x+y x = 20 b = lambda y : x+y a(10) >> 30
b(20) >> 30
lambda表达式中的x是一个自由变量, 在运行时绑定值,而不是定义时就绑定,这跟函数的默认值参数定义是不同的。 因此,在调用这个lambda表达式的时候,x的值是执行时的值。例如:
x = 10
a(10) >> 20 x = 20 b(10) >> 30
如果想让某个匿名函数在定义时就捕获到值,可以将那个参数值定义成默认参数即可,就像下面这样:
x = 10
a = lambda y, x=x: x+y
x = 20
b = lambda y,x=x: x+y a(10) >> 20
b(10) >> 30
通过在一个循环或列表推导中创建一个lambda表达式列表,并期望函数能在定义时就记住每次的迭代值。
# 错误写法 a = [lambda x:x+n for n in range(4)] for f in a:
f(0)
print(f(0))
上面的写法输出全是4,跟刚开始的例子一样,函数运行时,n的值是迭代的最后一个值。
可以通过使用函数默认值参数形式,lambda函数在定义时就能绑定到值。
a = [lambda x,n=n:x+n for n in range(4)] for f in a:
f(0)
print(f(0))
4、函数返回多个值
希望构造一个返回多个值得函数,函数直接return一个元祖就行。
def func():
return 1,2,3
a,b,c = func()
a >> 1
b >> 2
c >> 3
尽管func()看上去返回了多个值,实际上是先创建了一个元祖然后返回的,这个语法看上去比较奇怪,实际上我们使用的是用逗号生成的一个元祖,而不是用括号。比如下面:
a = (1,2)
a >> (1,2) a = 1,2
a >> (1,2)
当我们调用返回一个元祖的函数时候,通常我们会把结果赋值给多个变量,其实这就是元祖解包,返回结果也可以赋值给单个变量,这时候这个变量就是函数返回的那个元祖本身了。
Python基础—初识函数(二)的更多相关文章
- python基础 (初识函数&函数进阶)
函数基础部分 .什么是函数? 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率. 2.定义函数 定义:def 关键词开头,空格之后接函数名 ...
- Python基础之函数二
函数的嵌套 通过名字就能理解,函数里是还可以套着函数用的.这么牛,下面就来看看几段代码,看看是怎么回事.注意:函数一定是先定义后使用. x=1234 def f1(): #定义一个主函数 x = 1 ...
- python基础(12):函数(二)
1. 函数参数 之前我们说过了传参,如果我们需要给⼀个函数传参,⽽参数⼜是不确定的,或者我给⼀个函数传很多参数,我的形参就要写很多,很⿇烦,怎么办呢,我们可以考虑使⽤动态参数. 形参的第三种: 动态参 ...
- Python 基础 面向对象之二 三大特性
Python 基础 面向对象之二 三大特性 上一篇主要介绍了Python中,面向对象的类和对象的定义及实例的简单应用,本篇继续接着上篇来谈,在这一篇中我们重点要谈及的内容有:Python 类的成员.成 ...
- python基础篇(二)
PYTHON基础篇(二) if:else,缩进 A:if的基础格式和缩进 B:循环判断 C:range()函数和len()函数 D:break,contiue和pass语句 for,while循环 函 ...
- Python基础初识
一.安装 暂时没空写,预留 二.python基础初识 2.1 注释 当行注释:# 被注释内容 多行注释:'''被注释内容''',或者"""被注释内容"" ...
- python基础之函数详解
Python基础之函数详解 目录 Python基础之函数详解 一.函数的定义 二.函数的调用 三.函数返回值 四.函数的参数 4.1 位置参数 4.2 关键字参数 实参:位置实参和关键字参数的混合使用 ...
- python基础——匿名函数
python基础——匿名函数 当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便. 在Python中,对匿名函数提供了有限支持.还是以map()函数为例,计算f(x)=x2时 ...
- python基础——返回函数
python基础——返回函数 函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个可变参数的求和.通常情况下,求和的函数是这样定义的: def calc_ ...
- python基础——sorted()函数
python基础——sorted()函数 排序算法 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个d ...
随机推荐
- Windows 提权-内核利用_2
本文通过 Google 翻译 Kernel Exploits Part 2 – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校 ...
- QT5.14.1+Win7 64+Oracle11gR2 Qt连接数据库
原文链接 1.QT5.14下OCI驱动编译完整步骤 1.安装qt的时候手动选择安装源码资源(默认不安装Source的) 2.进入QT安装目录下E:\Qt5.14\5.14.0\Src\qtbase\s ...
- AXUI前端框架v3版本已经发布,底层完全改写,基于原生技术标准,想走得更远!
AXUI的v3版本已经发布! AXUI框架已经经历了第一代和第二代的迭代,充分认识到纯CSS和HTML的局限性,也意识到过多手动编写代码会影响用户体验.因此,AXUI的目标是:既满足原生前端的标准,又 ...
- angular使用nz-zorro的时间选择器,设置可选时间范围
备份一下 https://blog.csdn.net/qq_34790644/article/details/87098960 https://blog.csdn.net/fsxxzq521/arti ...
- 变异凯撒-python脚本调整ascii码转字符串
题目: 加密密文:afZ_r9VYfScOeO_UL^RWUc 格式:flag{ } 结合题目变异凯撒,第一个字符a到f加了5,第二个字符f到l加了6,推断每个字符都在前一个字符基础上+1. 编写py ...
- 理解和使用Oracle 日志分析工具-LogMiner
分类专栏: oracle日志 原文地址:https://blog.csdn.net/wishfly/article/details/660747 Oracle LogMiner 是Oracle ...
- WebKit Inside: 渲染树
经过CSS的匹配,就要进入渲染树的构建. 渲染树也叫RenderObject树,因为渲染树上每一个节点,都是RenderObject的子类. 首先来看一下RenderObject的继承类图. 1 Re ...
- 爆肝 1 周,为我的白板工具支持了 mermaid 流程图,为 ai 生成流程图铺平道路
朋友们好,前一段时间在博客园推荐了我的白板工具 Drawnix,得到了很多朋友的支持,非常感谢,最近 Drawnix 又有了一些重要更新,其中最实用的应该是支持 mermaid 语法的流程图了. 这是 ...
- Python 迭代器和生成器概念
目录 迭代器的介绍 自定义迭代器 省略的迭代器 生产器的介绍 yield的普通用法 yield的高级用法 yidle的实际应用案例 总结 迭代器的介绍 迭代器的定义: 迭代器(Iterator)是 P ...
- Java 里的对象在虚拟机里面是怎么存储的?
Java 中的对象在虚拟机里的存储 在 Java 中,对象在虚拟机中的存储方式取决于 JVM 内存模型,主要存储在 堆(Heap) 中.对象的内存布局和管理方式会影响对象的创建.访问和销毁.下面详细解 ...