Python基本语法_函数属性 & 参数类型 & 偏函数的应用

简介: 目录目录前言软件环境Python Module的程序入口函数的属性Python函数的创建函数的参数必备参数缺省参数命名参数不定长参数匿名参数偏函数的应用前言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.'
相关文章
|
2月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
193 1
|
2月前
|
Java 数据处理 索引
(Pandas)Python做数据处理必选框架之一!(二):附带案例分析;刨析DataFrame结构和其属性;学会访问具体元素;判断元素是否存在;元素求和、求标准值、方差、去重、删除、排序...
DataFrame结构 每一列都属于Series类型,不同列之间数据类型可以不一样,但同一列的值类型必须一致。 DataFrame拥有一个总的 idx记录列,该列记录了每一行的索引 在DataFrame中,若列之间的元素个数不匹配,且使用Series填充时,在DataFrame里空值会显示为NaN;当列之间元素个数不匹配,并且不使用Series填充,会报错。在指定了index 属性显示情况下,会按照index的位置进行排序,默认是 [0,1,2,3,...] 从0索引开始正序排序行。
268 0
|
3月前
|
IDE 开发工具 开发者
Python类型注解:提升代码可读性与健壮性
Python类型注解:提升代码可读性与健壮性
279 102
|
8月前
|
索引 Python
Python的变量和简单类型
本文介绍了Python中变量命名规则、常用变量类型及字符串操作。变量命名需遵循字母、数字和下划线组合,不能以数字开头且不可与关键字冲突。字符串支持单引号、双引号或三引号定义,涵盖基本输出、转义字符、索引、拼接等操作。此外,还详细解析了字符串方法如`islower()`、`upper()`、`count()`等,帮助理解字符串处理技巧。
220 15
|
4月前
|
安全 JavaScript Java
Python中None与NoneType的真相:从单例对象到类型系统的深度解析
本文通过10个真实场景,深入解析Python中表示“空值”的None与NoneType。从单例模式、函数返回值,到类型注解、性能优化,全面揭示None在语言设计与实际编程中的核心作用,帮助开发者正确高效地处理“无值”状态,写出更健壮、清晰的Python代码。
446 3
|
4月前
|
缓存 数据可视化 Linux
Python文件/目录比较实战:排除特定类型的实用技巧
本文通过四个实战案例,详解如何使用Python比较目录差异并灵活排除特定文件,涵盖基础比较、大文件处理、跨平台适配与可视化报告生成,助力开发者高效完成目录同步与数据校验任务。
169 0
|
4月前
|
IDE API 开发工具
Python类型注解:让代码“开口说话”的隐形助手
Python类型注解为动态语言增添类型信息,提升代码可读性与健壮性。通过变量、函数参数及返回值的类型标注,配合工具如mypy、IDE智能提示,可提前发现类型错误,降低调试与协作成本。本文详解类型注解的实战技巧、生态支持及最佳实践,助你写出更高质量的Python代码。
212 0
|
4月前
|
Python
解决Python中AttributeError:'image'对象缺少属性'read_file'的问题策略。
通过上述策略综合考虑,您将能够定位问题并确定如何解决它。记住,Python社区很庞大,也很乐于帮助解决问题,因此不要害怕在求助时提供尽可能多的上下文和您已经尝试过的解决方案。
141 0
|
7月前
|
Python
Python技术解析:了解数字类型及数据类型转换的方法。
在Python的世界里,数字并不只是简单的数学符号,他们更多的是一种生动有趣的语言,用来表达我们的思维和创意。希望你从这个小小的讲解中学到了有趣的内容,用Python的魔法揭示数字的奥秘。
173 26
|
7月前
|
人工智能 安全 IDE
Python 的类型安全是如何实现的?
本文探讨了 Python 的类型安全实现方式。从 3.5 版本起,Python 引入类型提示(Type Hints),结合静态检查工具(如 mypy)和运行时验证库(如 pydantic),增强类型安全性。类型提示仅用于开发阶段的静态分析,不影响运行时行为,支持渐进式类型化,保留动态语言灵活性。泛型机制进一步提升通用代码的类型安全性。总结而言,Python 的类型系统是动态且可选的,兼顾灵活性与安全性,符合“显式优于隐式”的设计哲学。
148 2

推荐镜像

更多