python -- 函数以及函数式编程

函数以及函数式编程

到目前为止,我们的Python 代码已经实现了小的分块。它们都适合处理微小任务,

但是我们想复用这些代码,所以需要把大型代码织成可管理的代码段。代码复用的第一步是
使用函数,它是命名的用于区分的代码段。函数可以接受任何数字或者其他类型的输入作为参
数,并且返回数字或者其他类型的结果。

定义一个函数

为了定义Python 函数,你可以依次输入def、函数名、带有函数参数的圆括号,最后紧跟一个

冒号(:)。函数命名规范和变量命名一样(必须使用字母或者下划线_ 开头,仅能含有字母、
数字和下划线)。
我们先定义和调用一个没有参数的函数。下面的例子是最简单的Python 函数:

>>> def do_nothing():
...  pass

定义一个无参数函数

现在,定义一个无参数,但打印输出一个单

词的函数:

>>> def make_a_sound():
...     print('momoda')
...
>>> make_a_sound()
momoda
>>> def agree():
...     return True
...
#或者,调用这个函数,使用if 语句检查它的返回值:
>>> if agree():
...     print("Is true")
... else:
...     print("Is Flase")
...
Is true

定义一个有参函数

>>> def echo(str):
...     return str*2
...
>>> echo('abc')
'abcabc'
>>>
def fruit_color(color):
    if color == 'red':
        print('这可能是一个苹果,或者是西红柿')
    elif color == 'yellow':
        print('这或许是一个香蕉也说不定')
    elif color == 'blue':
        print('一定是蓝莓吧')
    else:
        print('我可猜不到这是什么')
fruit_color('red')

位置参数

下面创建一个带有位置参数的函数,并且返回一个字典:

def menu(a,b,c):
    return {'a':a,'b':b,'c':c}
print(menu('a','b','c’))
{'a': 'a', 'b': 'b', 'c': 'c’}
#尽管这种方式很常见,但是位置参数的一个弊端是必须熟记每个位置的参数的含义。在调
#用函数menu() 时误把最后一个参数当作第一个参数,会得到完全不同的结果:
print(menu('c','b','a'))
{'c': 'a', 'b': 'b', 'a': 'c'}

关键字参数

为了避免位置参数带来的混乱,调用参数时可以指定对应参数的名字,甚至可以采用与函

数定义不同的顺序调用:

def menu(a,b,c):
    return {'a':a,'b':b,'c':c}
print(menu(c='c',b='b',a='a’))
当然也可以混合使用
def menu(a,b,c):
    return {'a':a,'b':b,'c':c}
print(menu(a='a',c='c',b='b'))。

指定默认参数值

举例:

def menu(a,b,c):
    return {'a':a,'b':b,'c':c}
print(menu(c='b',b='a’))

报错,缺少参数,实际上我们可以设置参数默认值

def menu(a='a',b='b',c='c'):
    return {'a':a,'b':b,'c':c}
print(menu(c='b',b='a’))
print(menu())

使用*收集位置参数

当参数被用在函数内部时, 星号将一组可变数量的位置参数集合成参数值的元组。

def my_print(*Str):
    print(Str)
my_print()
()
my_print(1,2,3,4,5):
(1, 2, 3, 4, 5)
my_print(1,2,3,'let\'s go’)
(1, 2, 3, "let's go")

使用两个星号可以将参数收集到一个字典中,参数的名字是字典的键,对应参数的值是字

典的值。下面的例子定义了函数print_kwargs(),然后打印输出它的关键字参数:

def my_print(**abc):
    print(abc)
my_print(a='a',b='b',c='c')

函数本身也是一个对象

之前提过Python 中一切都是对象,包括数字、字符串、元组、列表、字典和函数。函数是Python 中的一等公民,可以把它们(返回值)赋给变量,可以作为参 数被其他函数调用,也可以从其他函数中返回值。它可以帮助你在Python 中实现其 他语言难以实现的功能。

#为了测试,现在定义一个简单的函数answer(),它没有任何参数,仅仅打印输出数字42:
>>> def answer():
... print(42)
#运行该函数,会得到下面的结果:
>>> answer()
42
#再定义一个函数run_something。它有一个参数func,这个参数是一个可以运行的函数的名字:
>>> def run_something(func):
...  func()
#将参数answer 传到该函数,在这里像之前碰到的一样,把函数名当作数据使用:
>>> run_something(answer)
42
########################################
#我们来运行一个带参数的例子。定义函数add_args(),它会打印输出两个数值参数(arg1和arg2)的和:
>>> def add_args(arg1, arg2):
... print(arg1 + arg2)
#那么,add_args() 的类型是什么?
>>> type(add_args)
<class 'function'>
#此刻定义一个函数run_something_with_args(),它带有三个参数:
#• func——可以运行的函数
#• arg1——func 函数的第一个参数
#• arg2——func 函数的第二个参数
>>> def run_something_with_args(func, arg1,arg2):
        add_args(arg1, arg2)
>>> run_something_with_args(add_args, 5, 9)
14

内部函数

内部函数可以看作一个闭包。闭包是一个可以由另一个函数动态生成的函数,并且可以改变和存储函数外创建的变量的值。

>>> def outer(a, b):
    ... def inner(c, d):
        ... return c + d
    ... return inner(a, b)
...
>>>
>>> outer(4, 7)
11
#########################
def fun5():
    def sayhello(name):
        print("hello ", name)
    return sayhello     #返回的是函数名称
fun5()("zhangsan")

匿名函数:lambda()函数

edit_story(stairs, lambda word: word.capitalize() + '!')

map

map(funcname, list)

map(function, sequence[, sequence, ...]) -> list:将function作用于给定序列的每一个元素,

并将结果作为list返回;如果函数中需要多个参数则从多个序列中读取(python3里面,map()
的返回值已经不再是list,而是iterators, 所以想要使用,只用将iterator 转换成list 即可)

def square(x):
    return x**2
map(square, [1,2,3,4,5])


f1 = lambda x:x**2  #lambda表达式就是一个匿名函数
print(f1(3))
i1 = map(f1, [1,2,3,4,5])
print(list(i1))

reduce

reduce(function, sequence[, initial]) -> value:与map相比 , reduce类似于一个聚合类的

应用方法, 把list中的参数, 依次传递给funcname, 每次funcname的参数都是上个funcname
执行结果和下一个list中的元素, 所以, funcname 的 参数必须是两个. 从执行过程看, 有点像递
归.如果指定了initial则首先从此值和第一个元素开始计算。

def sum(x,y):
    return x+y
print(functools.reduce(sum, [1, 2, 3, 4, 5]))
print(functools.reduce(lambda x,y:x+y, [1,2,3,4,5]))
print(functools.reduce(lambda x,y:max([x,y]), [1,2,3,4,5]))

filter()

filter(function or None, sequence) -> list,tuple,string:

调用一个布尔类型的函数来迭代遍历每个seq中的元素,返回使得func返回为true的

元素的序列。

print(list(filter(lambda x:isinstance(x, (int)), [1,2,"3"])))
print(list(filter(lambda x:x>2, [1,2,3])))

sorted

sorted( list, [comp_func])

排序方法, 第二个是可选参数, 根据可选参数返回的值, 对结果进行排序, comp_func

接受两个参数(x, y), 最终返回的结果应该是-1.0,1, 如果返回的是-1, 表示x , 0表示x=y,
1表示x>y, 所以, 实际的排序可以自定义

print(sorted([4,6,1,2,3]))
print(sorted([4,6,1,2,3], reverse=True))
print(sorted([1,2,3,4,5,6],key=cmp_to_key(lambda x,y:y-x)))

命名空间和作用域

一个名称在不同的使用情况下可能指代不同的事物。Python 程序有各种各样

的命名空间,它指的是在该程序段内一个特定的名称是独一无二的,它和其他同名的
命名空间是无关的。每一个函数定义自己的命名空间。如果在主程序(main)中定义
一个变量x,在另外一个函数中也定义x 变量,两者指代的是不同的变量。

每个程序的主要部分定义了全局命名空间。因此,在这个命名空间的变量是

全局变量。

animal = 'cat'
>>> def print_global():
. . . print('inside print_global:',animal)
. . .
>>> print('outside print_global:',animal)
outside print_global: cat
>>> print_global()
inside print_global: cat
####################
#在函数中改变全局变量,会报错:
>>> def change_and_print_global():
... print('insid
change_and_print_global:',animal)
... animal = 'dog'
... print('after the change:',animal)
...
>>> change_and_print_global()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in
change_and_print_global
UnboundLocalError: local variable
'animal' referenced before assignment

如果在函数中不声明关键字global,Python 会使用局部命名空间,同时变量也是局

部的。函数执行后回到原来的命名空间。
Python 提供了两个获取命名空间内容的函数:

• locals() 返回一个局部命名空间内容的字典;

• globals() 返回一个全局命名空间内容的字典。

生成器

生成器是用来创建Python 序列的一个对象。目的就是为了避免一下子生成的数据太多占用大量内存,生成器会在数据被用到时生成数据。

def my_range(first, last, step=1):
    n = first
    while n<last:
        yield n #yield是一个关键字,使用yeild的函数实际上一个生成器
        n+=step
print(my_range())
#<generator object my_range at 0x0000021FC5AE>

装饰器

参考文章1参考文章2

名称中_和__的用法

以两个下划线__ 开头和结束的名称都是Python 的保留用法。因此,在自定义的变量

中不能使用它们。选择这种命名模式是考虑到开发者一般是不会选择它们作为自己的
变量的。

if __name__ == '__main__':
    print("这里是入口")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容