Python基本语法_函数属性 & 参数类型 & 偏函数的应用
目录
前言
Python除了有丰富的标准库之外,还可以自己定义满足自身需求的类和函数。本篇主要介绍如何创建Python自定义函数。
软件环境
- 系统
- UbuntuKylin 14.04
- 软件
- Python 2.7.4
- IPython 4.0.0
Python Module的程序入口
因为一个Python的程序文件同时也是一个模块文件,而且我们希望可以更好的实现类和函数的代码重用性、节省内存资源、提高执行效率。即,我希望主程序仅是在被期望执行的时候才会被执行而不会自动执行。所以我们会在每一个Python module文件中定义一个程序的入口,当我们直接执行Python module的时候会自动执行主程序。当我们一个Python module被别的程序导入时,则仅仅会导入在Python module文件中定义的类和函数。
我们一般会在Python module文件中的主程序前使用下面的一条语句:
if __name__ == '__main__':
__name__是模块的一个属性,其作用是调用当前模块的名称,若此模块是直接执行时,__name__ == ‘__main__’ 。当此模块是被其他程序import时,__name__的值为此模块的名称。
具体的Python module文件结构,请参考:http://blog.csdn.net/jmilk/article/details/48573995
Update: 2016-10-09
Python module程序入口最大的好处在于我们可以利用上述的这个特性来为一个 Module 编写测试代码, 当我们直接运行这个 module 文件的时候, 我们可以通过测试代码的实现来检验我们所定义的函数的输出和输出是否正确, 为每一个由必要测设的 module 文件写上测试代码是一个优秀的程序员所具备的编程习惯.
函数的属性
函数是对程序逻辑进行结构化或过程化的一种编程方法, 函数有助于节省代码空间, 也可以利于保持程序一致性(修改一处, 所有代用都会跟着改变).
函数的属性可以在定义函数时同时定义函数属性, 也可以在函数声明外定义函数属性.
EXAMPLE: 可以通过句点标识符和直接赋值的方法为一个函数添加属性.
In [2]: foo()
in foo()
In [3]: foo.__dict__
Out[3]: {}
In [4]: foo.name = 'jmilkfan'
In [5]: foo()
in foo()
In [6]: foo.__dict__
Out[6]: {'name': 'jmilkfan'}
In [7]: foo.name
Out[7]: 'jmilkfan'
还可以通过下面这种方式来定义函数属性
In [15]: foo.__dict__['age'] = 24
In [16]: foo.__dict__
Out[16]: {'age': 24, 'name': 'jmilkfan'}
In [17]: foo.age
Out[17]: 24
NOTE: 这里可以看出函数对象的 __dict__
特殊属性包含了函数对象的属性和属性值.
Python函数的创建
一般格式:
def functionName(parameters):
"""Document"""
函数体
return [expression]
创建一个自定义函数需要遵循下面几个规则:
1.函数代码块以def关键词开始,接着函数标识符、圆括号()和代码块起始标识 : 号。
2.任何传入参数和自变量都必须放在()。()内可以用于定义参数。当有多个参数时,使用逗号隔开。
3.函数体的第一行语句可以使用文档字符串"""Document"""
一般用作存放函数的使用说明。
在Python中,函数也是一个对象,( )中表示对可调用函数对象的一种调度,可调用的函数对象一定会继承了可调用的方法call( )。这也是用来检查一个函数可否能够被调用的依据。
callable(functionName)
若输出为True,表示对象functionName为可调用函数对象,其继承了call()方法,是一个函数。
In [5]: callable(sys.stdout.write)
Out[5]: True
函数的参数
Python有下面几种函数参数类型:
1.必备参数
2.命名参数
3.缺省参数
4.不定长参数
5.匿名参数
必备参数
必备参数是在自定义函数时,最常见的参数类型。必备参数的使用有下面几点要求:
1.在调用函数时,以形参与实参对应的顺序来确定形参的值并传入函数。
2.调用此函数时,传递的实参的数量必须与声明时定义的形参的数量一致。
In [19]: %pycat func1Test.py
#!/usr/bin/env python
#Filename:func1Test.py
def DoubleCheckInput(input1,input2):
if input1 == input2:
print "Your enter the %s" % input1
else:print "Two input iis not consistent!"
return "Done"
if __name__ == '__main__':
enter1 = raw_input("Ple enter your name:")
enter2 = raw_input("ple enter your name again:")
DoubleCheckInput(enter1,enter2)
In [20]: run func1Test.py
Ple enter your name:Jmilk
ple enter your name again:Jmilk
Your enter the Jmilk
注意:当传递的参数数目不一致时,会触发下面的异常:
In [23]: %pycat func1Test.py
#!/usr/bin/env python
#Filename:func1Test.py
def DoubleCheckInput(input1,input2):
if input1 == input2:
print "Your enter the %s" % input1
else:print "Two input iis not consistent!"
return "Done"
if __name__ == '__main__':
enter1 = raw_input("Ple enter your name:")
enter2 = raw_input("ple enter your name again:")
DoubleCheckInput(enter1)
In [24]: run func1Test.py
Ple enter your name:Jmilk
ple enter your name again:Jmilk
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/usr/local/src/pyScript/func1Test.py in <module>()
11 enter1 = raw_input("Ple enter your name:")
12 enter2 = raw_input("ple enter your name again:")
---> 13 DoubleCheckInput(enter1)
TypeError: DoubleCheckInput() takes exactly 2 arguments (1 given)
缺省参数
缺省参数既默认参数。顾名思义,缺省参数可以实现在调用函数却没有指定实参时,可以为形参数提供一个默认值。相对的,当缺省参数对应的实参有传递值时,缺省参数的默认值会被覆盖。从而实参的数目未必一定会与形参的数目一致,因为使用了缺省参数。格式:
def functionName([para1,...,]paras=defaultValues)
In [46]: %pycat func1Test.py
#!/usr/bin/env python
#Filename:func1Test.py
import sys
def DoubleCheckInput(input1,input2='Jmilk'):
if input1 == input2:
print "Your enter the %s" % input1
else:print "Two input iis not consistent!"
return "Done"
if __name__ == '__main__':
enter1 = raw_input("Ple enter your name:")
# enter2 = raw_input("ple enter your name again:")
DoubleCheckInput(enter1)
In [47]: run func1Test.py
Ple enter your name:Jmilk
Your enter the Jmilk
注意:即便缺省参数会为形参提供一个默认的值,但是在Python的编译过程的语法检查时,参数的匹配依旧是按照顺序传递。所以一般而言,当你希望使用缺省参数的值的时候,需要在定义函数的参数列表时,缺省参数一定要置于必备参数和命名参数之后。避免在参数传递的时候,实参在将参数列表前端的缺省参数覆盖后,却没有实参传递给必备参数。下面是一个例子:
In [56]: %pycat func1Test.py
#!/usr/bin/env python
#Filename:func1Test.py
import sys
def DoubleCheckInput(input1='Jmilk',input2):
if input1 == input2:
print "Your enter the %s" % input1
else:print "Two input iis not consistent!"
return "Done"
if __name__ == '__main__':
# enter1 = raw_input("Ple enter your name:")
enter2 = raw_input("ple enter your name again:")
DoubleCheckInput(enter2)
In [57]: run func1Test.py
File "/usr/local/src/pyScript/func1Test.py", line 4
def DoubleCheckInput(input1='Jmilk',input2):
SyntaxError: non-default argument follows default argument
语法错误:非缺省参数不能在缺省参数之后
命名参数
命名参数也称之为关键字参数, 其仅针对函数的调用, 让调用者通过函数调用中的参数名字赋值来将实参映射到形参, 有下面几个要点:
1.调用时,用赋值的方式来为函数传入参数,调用格式:
functionName(formPara1=actualPara1[,...])
2.可以以任意顺序来指定参数
In [40]: %pycat func1Test.py
#!/usr/bin/env python
#Filename:func1Test.py
import sys
def DoubleCheckInput(input1,input2):
if input1 == input2:
print "Your enter the %s" % input1
else:print "Two input iis not consistent!"
return "Done"
if __name__ == '__main__':
enter1 = raw_input("Ple enter your name:")
enter2 = raw_input("ple enter your name again:")
DoubleCheckInput(input2=enter2,input1=enter1)
In [41]: run func1Test.py
Ple enter your name:Jmilk
ple enter your name again:Jmilk
Your enter the Jmilk
下面举一个命名参数和缺省参数一结合使用的例子:
In [7]: %pycat func1Test.py
#!/usr/bin/env python
#Filename:func1Test.py
import sys
def printYourEnter(input1,input2='Jmilk',input3='23'):
print input1
print input2
print input3
if __name__ == '__main__':
enter1 = raw_input("Ple enter your living cities:")
enter2 = raw_input("ple enter your name:")
enter3 = raw_input("Ple enter your age:")
printYourEnter(enter1)
In [8]: run func1Test.py
Ple enter your living cities:BJ
ple enter your name:
Ple enter your age:
BJ
Jmilk
23
在上面的例子中使用了缺省参数,当没有实参传递到函数的时候,形参会使用默认值。但在有些情况中,我们希望可以重新指定形参input3的值,而且希望继续使用input2的默认值。在大多数编程语言中,想要实现上面的要求,必须要使用3个参数来调用函数,即必须重新指定input2的值。但是在Python中因为命名参数类型,所以我们可以突破参数顺序的限制。将上面的例子修改为:
In [13]: %pycat func1Test.py
#!/usr/bin/env python
#Filename:func1Test.py
import sys
def printYourEnter(input1,input2='Jmilk',input3='23'):
print input1
print input2
print input3
if __name__ == '__main__':
enter1 = raw_input("Ple enter your living cities:")
enter2 = raw_input("ple enter your name:")
enter3 = raw_input("Ple enter your age:")
printYourEnter(input1=enter1,input3=enter3)
In [14]: run func1Test.py
Ple enter your living cities:BJ
ple enter your name:
Ple enter your age:24
BJ
Jmilk
24
可以看见,当我没有传递input2,仅仅是传递了input1、input3,而input2还是使用了默认值,而不会因为没有指定命名参数导致input2被覆盖而input3使用默认值的情况。但是要注意的一点是,即便结合使用了命名参数和缺省参数,仍然无法改变non-default parameter not follows the default parameter的语法规则。
不定长参数
不定长参数也称之为参数组或冗余参数, 当你希望一个函数可以接受处理比当初声明定义函数时更多的参数,可以使用不定长参数。即,实现了函数的参数冗余。当传递的实参数目比函数的形参更多时,一般会报错。但函数中的不定长参数可以用来吸收多余的参数。注意:不定长参数仅允许放到函数形参列表的最后。格式:
def functionName([para1,para2,...,]*indefinitePara):
def functionName([para1,para2,...,]**indefinitePara):
def functionName([para1,para2,...,]*indefinitePara1, **indefinitePara2):
其中的 “*” 标识了不定长参数为 (非关键字参数) 会存储所有非关键字的冗余参数(没有在实参列表内指定关键字,EG. name='Jmilkfan'
),并将冗余的参数存储为Tuple类型对象, 也可以向该形参传递一个 Tuple 类型的参数组, 两者的效果是一样的. 只是前者在函数内处理成 Tuple 的形式, 后者在调用之前就已经整理成 Tuple 了。
Example1:
In [23]: %pycat func1Test.py
#!/usr/bin/env python
#Filename:func1Test.py
import sys
def printYourEnter(input1,*indePara):
print input1
print indePara
for var in indePara:
print var
if __name__ == '__main__':
enter1 = raw_input("Ple enter your living cities:")
enter2 = raw_input("ple enter your name:")
enter3 = raw_input("Ple enter your age:")
printYourEnter(enter1,enter2,enter3)
In [24]: run func1Test.py
Ple enter your living cities:BJ
ple enter your name:Jmilk
Ple enter your age:23
BJ
('Jmilk', '23')
Jmilk
23
上面例子的函数中使用了不定长参数*indePara,来存放enter2多余的enter3两个实参。并且是以元组的数据类型来存储。
Example2:
而 “**” 表示为一个 (关键字参数),以字典的数据类型来存储冗余实参, 也可以向该形参传递一个 Dict 类型的实参。
In [4]: %pycat func1Test.py
#!/usr/bin/env python
#Filename:func1Test.py
def printYourEnter(input1,**indePara):
print input1
print indePara
if __name__ == '__main__':
enter1 = raw_input("Ple enter your living cities:")
enter2 = raw_input("ple enter your name:")
enter3 = int(raw_input("Ple enter your age:"))
printYourEnter(enter1,name=enter2,age=enter3)
In [5]: run func1Test.py
Ple enter your living cities:BJ
ple enter your name:Jmilk
Ple enter your age:23
BJ
{'age': 23, 'name': 'Jmilk'}
在调用函数时,使用key=value的映射关系元素,传递实参。本质上是传递了key的引用和value的数据两个值,并且传递到函数中的**indePara字典类型。要注意这与命名参数的区别,命名参数是为了可以乱序传递实参,而不定长参数是为了将多余的实参保存在函数中的Tuple或Dictionary类型对象中。
注意:以Tuple或Dic作为形参吸收实按冗余时,若实参中均没有多余的元素或没有映射关系元素时,会自动的为函数中的Tuple或Dic类型对象填入空值,避免报错。
In [9]: %pycat test.py
#!/usr/bin/env python
def test(x,*args,**kwargs):
print x
print args
print kwargs
test(1)
In [10]: run test.py
1
()
{}
还需要注意的是:实参的映射关系元素中的key,不可以与已经存在的普通形参同名。否则会报错
In [13]: %pycat test.py
#!/usr/bin/env python
def test(x,**kwargs):
print x
print kwargs
test(1,x=1,y=2)
In [14]: run test.py
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/usr/local/src/pyScript/test.py in <module>()
4 print kwargs
5
----> 6 test(1,x=1,y=2)
TypeError: test() got multiple values for keyword argument 'x'
主要是避免命名参数和不定长参数的冲突。
匿名参数
匿名函数,即lambda函数。此函数能够快速的创建出单行最小行函数并用于任何需要函数的地方,使用匿名参数有下面几个要点:
1.无须使用def关键字来进行声明。
2.lambda函数可以接受任何数量的实参,但只会且仅返回一个表达式的值。
3.lambda函数不能包含有命令和多个表达式。
4.不能直接调用print语句,因为lambda函数是单行函数且此行只能为表达式。
5.lambda函数拥有自己的命名空间,不能访问除自身参数列表之外的全局命名空间内的参数。
6.lambda最大的优势在于,可以不占用栈内存从而增加执行效率。
lambda函数的定义格式:
functionName = lambda [arg1[,arg2,...]]:expression
调用格式:
functionName(arg1[,arg2,..])
Example:
In [76]: %pycat lamTest.py
#!/usr/bin/env python
#Filename:lamTest.py
n = lambda x,y:x*y
print type(n)
print type(n(2,3))
print n(2,3)
In [77]: run lamTest.py
<type 'function'>
<type 'int'>
6
lambda在定义时会返回一个需要接收的函数对象,在调用后会返回一个类型对象。
偏函数的应用
偏函数的概念:就是将函数式编程、缺省参数和冗余参数结合在一起,将任意数量(顺序)的参数转化为另一个带有剩余参数的函数对象,从而实现截取函数功能(偏向)的效果。
NOTE:偏函数需要 functools Module 的支持。
EXAMPLE 1:将二进制数转化为十进制
In [1]: int('10101010', base=2)
Out[1]: 170
一般而言我们会使用上述的方式来执行,但有些时候会觉得能不能将 int() 函数的 base 参数临时的设置成缺省参数呢?这样的话就可以获得一个专门为了实现 *将二进制数转化为十进制
* 功能的函数了。下面就是偏函数其中一个小的应用实例:
In [2]: from functools import partial
In [3]: baseTwo = partial(int, base=2)
In [5]: baseTwo('10101010')
Out[5]: 170
将 int() 函数的 base 参数定义为缺省参数,并返回给一个新的变量,这样就像是生成了一个新的函数,EG.
baseTwo(x) == int(x, base=2)
。
除此之外,我们还可以利用函数属性的特性来为这个 “新定义” 的函数编写文档。
In [6]: baseTwo.__doc__ = 'Convert base 2 string to an int.'
In [8]: baseTwo.__doc__
Out[8]: 'Convert base 2 string to an int.'
Python基本语法_函数属性 & 参数类型 & 偏函数的应用的更多相关文章
- Python基本语法_函数_参数的多类型传值
前言 上一篇主要介绍了Python函数的参数类型,本篇继续学习Python函数多类型传值. 目录 前言 目录 软件环境 参数的多类型传值 向函数传递Tuple 向函数传递List 向函数传递Dicti ...
- Python基本语法_函数_返回值
目录 目录 前言 函数的返回值 在函数中Return和Print的区别 函数中的文档 前言 函数的返回值是函数重要的组成部分.函数的根本在于实现程序的部分功能,所以很多时候我们需要将函数执行后的结果返 ...
- Python函数中参数类型
在学习Python函数的时候,函数本身的定义和调用并不是很复杂,但是函数的参数类型和用法的确有些复杂.在此做一个小结,加深理解. Python参数的定义 负责给函数提供一些必要的数据或信息,以保证函数 ...
- Python 基本语法,文件读写,数据结构和类型
Python 基本语法,文件读写,数据结构和类型 1.基本语法 解释型(无需编译).交互式.面向对象.跨平台.简单好用 中文编码:http://www.cnblogs.com/huxi/archive ...
- python学习第五讲,python基础语法之函数语法,与Import导入模块.
目录 python学习第五讲,python基础语法之函数语法,与Import导入模块. 一丶函数简介 1.函数语法定义 2.函数的调用 3.函数的文档注释 4.函数的参数 5.函数的形参跟实参 6.函 ...
- python基础语法5 函数定义,可变长参数
函数 1.什么是函数 函数就是一种工具. 可以重复调用 2.为什么要用函数 1.防止代码冗(rong)余 2.代码的可读性差 3.怎么用函数 1.定义函数-->制造工具 2.调用函数--> ...
- Python基本语法_基本数据类型_序列类型详解
目录 目录 序列 序列的标准操作符 切片操作符 一个例子 字符串的连接 序列的功能函数 enumerate 枚举出序列对象的元素 len 获取序列对象的长度 min 取出sequence中的最小值 m ...
- [c++][语言语法]函数模板和模板函数 及参数类型的运行时判断
参考:http://blog.csdn.net/beyondhaven/article/details/4204345 参考:http://blog.csdn.net/joeblackzqq/arti ...
- 多测师讲解python _函数中参数__高级讲师肖sir
函数中讲解参数: 形参和实参的认识 函数无参数的调用 函数单个参数的调用 函数多个参数的调用 # #调试函数给默认参数传新值,则函数使用新值 # 注意:当多种参数同时出现在函数中,默认参数要放在最后的 ...
随机推荐
- iperf和iperf3详解
一.iperf server端: iperf -s -p 25001 -B 192.168.33.103 (-u) -s 指定server端 -p 指定端口(要和客户端一致) -B 绑定ip地址 - ...
- Linux centos :root密码忘记怎么办?
1 重启系统后出现GRUB界面在引导装载程序菜单上,用上下方向键选择你忘记密码的那个系统键入“e” 来进入编辑模式. 2 接下来你可以看到如下图所示的画面,然后你再用上下键选择最新的内核(这里是第二行 ...
- 17JQuery高级
1. 动画 1. 三种方式显示和隐藏元素 1. 默认显示和隐藏方式 1. show([speed,[easing],[fn]]) 1. 参数: 1. speed:动画的速度.三个预定义的值(" ...
- [易学易懂系列|rustlang语言|零基础|快速入门|(14)|Impls & Traits实现与特征]
[易学易懂系列|rustlang语言|零基础|快速入门|(14)] 有意思的基础知识 Impls & Traits实现与特征 我之前说到的struct结构体,其实就类似于面向对象语言中的类cl ...
- HTML5日期时间输入类型注意事项(time,date)
原文链接:http://www.webhek.com/post/html5-date.html 1.HTML5规范里只规定date新型input输入类型,并没有规定日历弹出框的实现和样式.所以,各浏览 ...
- mysql 在gtid环境下缺少一部分binlog部署从库
我的环境: 有两台linux服务器 一台是192.168.1.1 mysql 端口3301 一台是192.168.1.2 mysql 端口3303 要讨论如何恢复从库,我们得先来了解如下一些概 ...
- BZOJ3329 Xorequ[数位DP+递推矩阵快速幂]
数 位 D P 开 long long 首先第一问是转化. 于是就可以二进制下DP了. 第二问是递推,假设最后$n-1$个01位的填法设为$f[i-1]$(方案包括 ...
- STM32CUBE+KEIL+Compiler V6使用方法
可以参考:https://blog.csdn.net/PeterSun01/article/details/90445439https://www.jianshu.com/p/18a58fee94ce ...
- 处理离散型特征和连续型特征共存的情况 归一化 论述了对离散特征进行one-hot编码的意义
转发:https://blog.csdn.net/lujiandong1/article/details/49448051 处理离散型特征和连续型特征并存的情况,如何做归一化.参考博客进行了总结:ht ...
- k8s-insight测试
eureka apiVersion: v1 kind: Pod metadata: name: eureka labels: ccb: eureka spec: containers: - name: ...