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 ...
随机推荐
- Golang 入门 : 文件名、关键字与标识符
Go 的源文件以 .go 为后缀名存储在计算机中,这些文件名均由小写字母组成,如 scanner.go .如果文件名由多个部分组成,则使用下划线 _ 对它们进行分隔,如 scanner_test.go ...
- Windows 10右键添加 "在此处打开命令窗口" 菜单
1.添加右键菜单的两种效果: 第一种是在 桌面/文件夹窗口中/选中文件夹上直接点击右键,显示"在此处打开命令窗口"选项,如图: 第二种是在 桌面/文件夹窗口中/选中文件夹上按住Sh ...
- BUUCTF--Dangeous RSA(小e)
对于e很小,可以直接采取爆破的手段,直接上代码 点击查看代码 #python3 ## -*- coding: utf-8 -*-# import binascii from gmpy2 import ...
- 抽象类和接口的对比、及各自的使用场景--java进阶day02
1.区别 2.各自的使用场景 1.抽象类的使用场景 如图,有三个类,其中存在共性,我们就会写一个父类并抽取出共性的东西,但有的方法难免会描述不清,所以我们就将其写为了抽象方法,抽象方法又得存在于抽象类 ...
- Tampermonkey 油猴脚本中文手册(出处:https://www.itblogcn.com/article/2233.html)
文章目录 @name @namespace @copyright @version @description @icon, @iconURL, @defaulticon @icon64, @icon6 ...
- mybatis数据的批量插入
1:xml的配置 <insert id="insertUserBatch"> insert into user(username, birthday, sex, add ...
- java基础之接口、多态
一.接口:是Java语言中一种引用类型[组数.类也是引用类型],内部主要就是封装了方法, 包括(抽象方法.默认方法.静态方法.私有方法) 格式: public interface 接口名称 { // ...
- 格林威治时间(Tue Jan 01 00:00:00 CST 2019)转Date
Excel导入时后台接受日期格式数据为[格林威治时间](例:Tue Jan 01 00:00:00 CST 2019) 格林威治时间转Date package com.cn; import java. ...
- 华为od机考2025A卷真题 -查找接口成功率最优时间段
题目描述与示例 题目描述 服务之间交换的接口成功率作为服务调用关键质量特性,某个时间段内的接口失败率使用一个数组表示,数组中每个元素都是单位时间内失败率数值,数组中的数值为 0~100 的整数,给定一 ...
- 看完这章你也会黑盒edu通杀
负责声明: 请勿利用文章内的相关技术从事非法测试,由于传播.利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关.该文章仅供学习用途 ...