【Python】(七)函数

简介: 【Python】(七)函数

1.函数前导


函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。


函数能提高应用的模块性,和代码的重复利用率。我们已经知道Python提供了许多内建函数,比如print()。但也可以自己创建函数,这被叫做用户自定义函数。


2.函数定义


你可以定义一个由自己想要功能的函数,以下是简单的规则:


函数代码块以def关键词开头,后接函数标识符名称和圆括号()。

任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。

函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。

函数内容以冒号起始,并且缩进。

Return[expression]结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。


语法:

def functionname( parameters ):
   "函数_文档字符串"
   function_suite


默认情况下,参数值和参数名称是按函数声明中定义的的顺序匹配起来的。


示例如下:

def printme( str ):
   "打印传入的字符串到标准显示设备上"
   print str
   return


3.函数调用


定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。


这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。


示例如下:

def printme( str ):
   "打印任何传入的字符串"
   print str;
   return;
 # Now you can call printme function
printme("我要调用用户自定义函数!");
printme("再次调用同一函数");


输出结果:

我要调用用户自定义函数!
再次调用同一函数


4.参数传递


在python中,类型属于对象,变量是没有类型的

a=[1,2,3]
a="w3cschool"


以上代码中,[1,2,3] 是 List 类型,"w3cschool"是String类型,而变量a是没有类型,她仅仅是一个对象的引用(一个指针),可以是List类型对象,也可以指向 String类型对象。


可更改(mutable)与不可更改(immutable)对象


在python中,strings, tuples, 和numbers是不可更改的对象,而 list,dict 等则是可以修改的对象。


不可变类型:变量赋值a=5后再赋值a=10,这里实际是新生成一个int值对象10,再让a指向它,而5被丢弃,不是改变a的值,相当于新生成了a。

可变类型:变量赋值la=[1,2,3,4] 后再赋值la[2]=5则是将list la的第三个元素值更改,本身la没有动,只是其内部的一部分值被修改了。


python 函数的参数传递:


不可变类型:类似c++的值传递,如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在 fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响 a 本身。

可变类型:类似c++的引用传递,如 列表,字典。如fun(la),则是将la真正的传过去,修改后fun外部的la也会受影响

python中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传不可变对象和传可变对象。


python 传不可变对象实例


实例(Python 2.0+)

def ChangeInt( a ):
    a = 10
b = 2
ChangeInt(b)
print b # 结果是 2


实例中有int对象2,指向它的变量是b,在传递给ChangeInt函数时,按传值的方式复制了变量b,a和b都指向了同一个 Int 对象,在a=10时,则新生成一个int值对象 10,并让a指向它。


按值传递参数和按引用传递参数(传可变对象实例)


所有参数(自变量)在Python里都是按引用传递。如果你在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。例如:

# 可写函数说明
def changeme( mylist ):
   "修改传入的列表"
   mylist.append([1,2,3,4]);
   print "函数内取值: ", mylist
   return
# 调用changeme函数
mylist = [10,20,30];
changeme( mylist );
print "函数外取值: ", mylist


传入函数的和在末尾添加新内容的对象用的是同一个引用。故输出结果如下:

函数内取值:  [10, 20, 30, [1, 2, 3, 4]]
函数外取值:  [10, 20, 30, [1, 2, 3, 4]]


5.参数


以下是调用函数时可使用的正式参数类型:


必备参数


必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。


调用printme()函数,你必须传入一个参数,不然会出现语法错误,示例如下:

#可写函数说明
def printme( str ):
   "打印任何传入的字符串"
   print str;
   return;
 #调用printme函数
printme();


输出结果:

Traceback (most recent call last):
  File "test.py", line 11, in <module>
    printme();
TypeError: printme() takes exactly 1 argument (0 given)


命名参数


命名参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。


使用命名参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。


示例如下:

#可写函数说明
def printinfo( name, age ):
   "打印任何传入的字符串"
   print "Name: ", name;
   print "Age ", age;
   return;
#调用printinfo函数
printinfo( age=50, name="miki" );


输出结果:

Name:  miki
Age  50


缺省参数


调用函数时,缺省参数的值如果没有传入,则被认为是默认值。


示例如下:

#可写函数说明
def printinfo( name, age = 35 ):
   "打印任何传入的字符串"
   print "Name: ", name;
   print "Age ", age;
   return;
#调用printinfo函数
printinfo( age=50, name="miki" );
printinfo( name="miki" );


输出结果:

Name:  miki
Age  50
Name:  miki
Age  35


不定长参数


如果需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述3种参数不同,声明时不会命名。基本语法如下:

def functionname([formal_args,] *var_args_tuple ):
   "函数_文档字符串"
   function_suite
   return [expression]


加了星号(*)的变量名会存放所有未命名的变量参数。选择不多传参数也可。如下实例:

# 可写函数说明
def printinfo( arg1, *vartuple ):
   "打印任何传入的参数"
   print "输出: "
   print arg1
   for var in vartuple:
      print var
   return;
# 调用printinfo 函数
printinfo( 10 );
printinfo( 70, 60, 50 );


以上实例输出结果:

输出:
10
输出:
70
60
50


6.匿名函数


类似Java,python 使用 lambda 来创建匿名函数。


lambda只是一个表达式,函数体比def简单很多。

lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。

lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。

虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。


lambda函数的语法只包含一个语句,如下:

lambda [arg1 [,arg2,.....argn]]:expression


示例如下:

#可写函数说明
sum = lambda arg1, arg2: arg1 + arg2;
#调用sum函数
print "Value of total : ", sum( 10, 20 )
print "Value of total : ", sum( 20, 20 )


输出结果:

Value of total :  30
Value of total :  40



return语句[表达式]退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。之前的例子都没有示范如何返回数值。


示例如下:

#coding=utf-8
#!/usr/bin/python
# 可写函数说明
def sum( arg1, arg2 ):
   # 返回2个参数的和."
   total = arg1 + arg2
   print "Inside the function : ", total
   return total;
 # 调用sum函数
total = sum( 10, 20 );
print "Outside the function : ", total


以上实例输出结果:

Inside the function :  30
Outside the function :  30


8.变量作用域


一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。


变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。两种最基本的变量作用域如下:


全局变量

局部变量


定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。


局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。


实例如下:

total = 0; # This is global variable.
# 可写函数说明
def sum( arg1, arg2 ):
   #返回2个参数的和."
   total = arg1 + arg2; # total在这里是局部变量.
   print "Inside the function local total : ", total
   return total;
#调用sum函数
sum( 10, 20 );
print "Outside the function global total : ", total


以上实例输出结果:

Inside the function local total :  30
Outside the function global total :  0


9.函数式编程


函数式编程的特点


把计算视为函数而非指令

纯函数式编程,不需要变量,没有副作用,测试简单

支持高阶函数,代码简洁

python支持的函数式编程


不是纯函数式编码:允许有变量

支持高阶函数:函数也可以作为变量传入

支持闭包:有了闭包就能返回函数

有限度地支持匿名函数


10.高阶函数


高阶函数:只能接收函数作为参数的函数


变量可以是指向函数

函数的参数可以接收变量

一个函数可以接收另一个函数作为参数

能接收函数作为参数的函数就是高阶函数


下面介绍几个常见的高阶函数


1.map()函数


map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。


例如,对于list [1, 2, 3, 4, 5, 6, 7, 8, 9] ,如果希望把list的每个元素都作平方,就可以用map()函数。 只需要传入函数f(x)=x*x,就可以利用map()函数完成这个计算(**注意: python3中map()返回iterators类型,不再是list类型。进行list转换即可 **):


示例如下:

def f(x):
    return x*x
print map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])


输出结果:

[1, 4, 9, 10, 25, 36, 49, 64, 81]


注意:map()函数不改变原有的 list,而是返回一个新的 list


2.reduce()函数


reduce()函数也是Python内置的一个高阶函数。reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。


例如,编写一个f函数,接收x和y,返回x和y的和:

def f(x, y):
    return x + y


调用 reduce(f, [1, 3, 5, 7, 9]) 时,reduce函数将做如下计算:

先计算头两个元素:f(1, 3),结果为4;
再把结果和第3个元素计算:f(4, 5),结果为9;
再把结果和第4个元素计算:f(9, 7),结果为16;
再把结果和第5个元素计算:f(16, 9),结果为25;
由于没有更多的元素了,计算结束,返回结果25。


上述计算实际上是对 list 的所有元素求和。虽然Python内置了求和函数sum(),但是,利用reduce()求和也很简单。


reduce()还可以接收第3个可选参数,作为计算的初始值。如果把初始值设为100,计算:

reduce(f, [1, 3, 5, 7, 9], 100)


结果将变为125,因为第一轮计算是:


计算初始值和第一个元素:f(100, 1),结果为101。


示例


Python内置了求和函数sum(),但没有求积的函数,请利用recude()来求积:


输入:[2, 4, 5, 7, 12]

输出:245712的结果

1 from functools import reduce
2 def prod(x, y):
3     return x*y
4 
5 print(reduce(prod,[2,4,5,7,12]))


注意:在python3.x后的版本中,reduce函数被划归到的functools库,因此使用reduce函数之前必须先引入functools库


3.filter()函数


filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list*,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。


例如,要从一个list [1, 4, 6, 7, 9, 12, 17]中删除偶数,保留奇数,首先,要编写一个判断奇数的函数:

def is_odd(x):
    return x % 2 == 1


然后,利用filter()过滤掉偶数:

filter(is_odd, [1, 4, 6, 7, 9, 12, 17])


结果:[1, 7, 9, 17]


利用filter(),可以完成很多有用的功能,例如,删除 None 或者空字符串:

def is_not_empty(s):
    return s and len(s.strip()) > 0
filter(is_not_empty, ['test', None, '', 'str', '  ', 'END'])


结果:[‘test’, ‘str’, ‘END’]


注意: s.strip(rm) 删除 s 字符串中开头、结尾处的 rm 序列的字符。


当rm为空时,默认删除空白符(包括’\n’, ‘\r’, ‘\t’, ’ '),如下:

a = '     123'
a.strip()


结果: ‘123’

a='\t\t123\r\n'
a.strip()


结果:‘123’


示例


请利用filter()过滤出1~100中平方根是整数的数,即结果应该是:


[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]


代码

import math
def is_sqr(x):
    a = math.sqrt(x)%1
    if a ==0.0:
        return True
    else:
        return False
l = filter(is_sqr, range(1,101))
print(list(l))


4.sort()函数


Python内置的 sorted()函数可对list进行排序:

>>> sorted([36, 5, 12, 9, 21])
[5, 9, 12, 21, 36]


但 sorted()也是一个高阶函数,它可以接收一个比较函数来实现自定义排序,比较函数的定义是,传入两个待比较的元素 x, y,如果 x 应该排在 y 的前面,返回 -1,如果 x 应该排在 y 的后面,返回 1。如果 x 和 y 相等,返回 0。


因此,如果我们要实现倒序排序,只需要编写一个reversed_cmp函数:

def reversed_cmp(x, y):
    if x > y:
        return -1
    if x < y:
        return 1
    return 0


这样,调用 sorted() 并传入 reversed_cmp 就可以实现倒序排序:

>>> sorted([36, 5, 12, 9, 21], reversed_cmp)
[36, 21, 12, 9, 5]


sorted()也可以对字符串进行排序,字符串默认按照ASCII大小来比较:

>>> sorted(['bob', 'about', 'Zoo', 'Credit'])
['Credit', 'Zoo', 'about', 'bob']


'Zoo’排在’about’之前是因为’Z’的ASCII码比’a’小。


示例


对字符串排序时,有时候忽略大小写排序更符合习惯。请利用sorted()高阶函数,实现忽略大小写排序的算法。


输入:[‘bob’, ‘about’, ‘Zoo’, ‘Credit’]

输出:[‘about’, ‘bob’, ‘Credit’, ‘Zoo’]

#-*- coding=utf8 -*- 
#这段代码在Python2.7可以运行,python3.x之后sorted函数不支持自定义比较函数,在python3.x中sorted函数的定义为
#sorted(iterable, /, *, key=None, reverse=False)
#可以通过将reverse参数设置为True来实现上面的功能
def cmp_ignore_case(s1, s2):
    if s1.lower()> s2.lower():
        return 1
    elif s1.lower()< s2.lower():
        return -1
    else:
        return 0
print sorted(['bob','about','Zoo','Credit'], cmp_ignore_case)


5.偏函数


当一个函数有很多参数时,调用者就需要提供多个参数。如果减少参数个数,就可以简化调用者的负担。


比如,int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换:

>>> int('12345')
12345


但int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做 N 进制的转换:

>>> int('12345', base=8)
5349
>>> int('12345', 16)
74565


假设要转换大量的二进制字符串,每次都传入int(x, base=2)非常麻烦,于是,我们想到,可以定义一个int2()的函数,默认把base=2传进去:

def int2(x, base=2):
    return int(x, base)


functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:

>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85


所以,functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时指定默认值,这样,新函数调用的难度就降低了。

目录
相关文章
|
1月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
162 1
|
1月前
|
算法 Java Docker
(Python基础)新时代语言!一起学习Python吧!(三):IF条件判断和match匹配;Python中的循环:for...in、while循环;循环操作关键字;Python函数使用方法
IF 条件判断 使用if语句,对条件进行判断 true则执行代码块缩进语句 false则不执行代码块缩进语句,如果有else 或 elif 则进入相应的规则中执行
248 1
|
1月前
|
Java 数据处理 索引
(numpy)Python做数据处理必备框架!(二):ndarray切片的使用与运算;常见的ndarray函数:平方根、正余弦、自然对数、指数、幂等运算;统计函数:方差、均值、极差;比较函数...
ndarray切片 索引从0开始 索引/切片类型 描述/用法 基本索引 通过整数索引直接访问元素。 行/列切片 使用冒号:切片语法选择行或列的子集 连续切片 从起始索引到结束索引按步长切片 使用slice函数 通过slice(start,stop,strp)定义切片规则 布尔索引 通过布尔条件筛选满足条件的元素。支持逻辑运算符 &、|。
140 0
|
2月前
|
设计模式 缓存 监控
Python装饰器:优雅增强函数功能
Python装饰器:优雅增强函数功能
267 101
|
2月前
|
缓存 测试技术 Python
Python装饰器:优雅地增强函数功能
Python装饰器:优雅地增强函数功能
205 99
|
2月前
|
存储 缓存 测试技术
Python装饰器:优雅地增强函数功能
Python装饰器:优雅地增强函数功能
185 98
|
2月前
|
缓存 Python
Python中的装饰器:优雅地增强函数功能
Python中的装饰器:优雅地增强函数功能
|
3月前
|
Python
Python 函数定义
Python 函数定义
468 155
|
4月前
|
PHP Python
Python format()函数高级字符串格式化详解
在 Python 中,字符串格式化是一个重要的主题,format() 函数作为一种灵活且强大的字符串格式化方法,被广泛应用。format() 函数不仅能实现基本的插入变量,还支持更多高级的格式化功能,包括数字格式、对齐、填充、日期时间格式、嵌套字段等。 今天我们将深入解析 format() 函数的高级用法,帮助你在实际编程中更高效地处理字符串格式化。
538 0
|
2月前
|
算法 安全 数据安全/隐私保护
Python随机数函数全解析:5个核心工具的实战指南
Python的random模块不仅包含基础的随机数生成函数,还提供了如randint()、choice()、shuffle()和sample()等实用工具,适用于游戏开发、密码学、统计模拟等多个领域。本文深入解析这些函数的用法、底层原理及最佳实践,帮助开发者高效利用随机数,提升代码质量与安全性。
572 0

推荐镜像

更多
下一篇
oss云网关配置