递归函数合式分解python_简学Python第三章__函数式编程、递归、内置函数

一、函数式编程

创建函数

一个函数式由关键字 def ,与函数名与括号冒号,和括号中的参数组成,当想要执行函数的时候只需要写上函数名加括号即可

格式: def function (parameter) 下面就创建一个函数#!/usr/bin/env python

# -*- coding:utf-8 -*-

#创建函数

def print_str():

print("Hello World")

#调用函数

print_str()

第一个函数

变量的作用域

我们看一个例子,在下面代码中我们先把变量 a=“haha” 然后在函数中把 a=“heihei” 最后执行这个函数,并输出变量a的结果

我们发现为什么a不等于 “heihei”,而是我们之前赋值的 “haha” 这个现象我们马上揭秘#!/usr/bin/env python

# -*- coding:utf-8 -*-

a = "haha"

#创建函数

def print_str():

a = "heihei"

print("Hello World")

#调用函数

print_str()

print("我是变量a:",a)

变量的作用域例一

全局变量与局部变量

很明显变量的作用域就是变量在哪一个范围内生效,如果出了这个范围则无法使用

全局变量:通常全局变量存活在脚本运行结束,并且所有的函数都可以访问它

局部变量:只能局部变量所在的函数内部调用,并且除非把局部变量声明成全局变量否则,其他函数均无法调用,并且局部变量

当所在的函数执行完成后就不存在了#!/usr/bin/env python

# -*- coding:utf-8 -*-

a = "haha"

#创建函数

def print_str():

a = "heihei"

print("我是局部变量a:",a)

#调用函数

print_str()

print("我是全局变量a:",a)

全局变量与局部变量

global

global就是可以把局部变量变成全局变量的,如果被声明的局部变量名与全局变量名一样的话,那么局部变量会覆盖全局变量,切

使用global声明变量需要在变量之前声明否则python会告诉你,你需要在 a 前面声明

报错提示:SyntaxWarning: name ‘a’ is assigned to before global declaration global a#!/usr/bin/env python

# -*- coding:utf-8 -*-

a = "haha"

#创建函数

def print_str():

global a

a = "heihei"

print("我是局部变量a:",a)

#调用函数

print_str()

print("我是全局变量a:",a)

gloable

二、传参与返回值

传参

函数用起来比较简单也容易理解,但是参数的变化就比较多了,在函数括号内就是参数,参数可以接收字符串,数字,也可以接收字典和列表

并且在调用的时候,我们还可以指定给哪个参数赋什么值#!/usr/bin/env python

# -*- coding:utf-8 -*-

#创建函数

def print_str(Name,Age,Aender):

print('''

Name:%s

Age:%s

Aender:%s

'''%(Name,Age,Aender))

#用户输入

in_name = input("请输入你的名字:")

in_age = input("请输入你的年龄:")

in_aender = input("请输入你的性别:")

#固定位置传参

print_str(in_name,in_age,in_aender)

print("----------------------------------")

#不固定位置传参

print_str(in_name,Aender=in_aender,Age=in_age)

传参

当我们想要传入列表或者字典时需要怎么办?#!/usr/bin/env python

# -*- coding:utf-8 -*-

def print_str(lists):

if type(lists) == list:

print('''

Name:%s

Age:%s

Aender:%s

'''%(lists[0],lists[1],lists[2]))

else:

print('''

Name:%s

Age:%s

Aender:%s

'''%(lists["name"],lists["age"],lists["aenber"]))

#传入列表

userlist = ["Ben","22","Man"]

print_str(userlist)

print("----------------------------------")

#传入字典

userdict = {"name":"Ben","age":"022","aender":"Man"}

print_str(userlist)

传入字典或列表

默认参数

在函数中还可以设置默认参数,默认参数的意思是这个参数你可以传值也可以不传值,当不传值的时候这个参数就等于默认值#!/usr/bin/env python

# -*- coding:utf-8 -*-

def print_str(lists,Country="China"):

if type(lists) == list:

print('''

Name:%s

Age:%s

Aender:%s

country:%s

'''%(lists[0],lists[1],lists[2],Country))

else:

print('''

Name:%s

Age:%s

Aender:%s

country:%s

'''%(lists["name"],lists["age"],lists["aenber"],Country))

#传入列表

userlist = ["Ben","22","Man"]

print_str(userlist)

print("----------------------------------")

#传入字典

userdict = {"name":"Ben","age":"022","aender":"Man"}

print_str(userlist,"America")

默认参数

非固定参数

非固定参数的意义在于可以接收任意个值,在你的函数不确定用户想传入多少个值的时候使用,当然在调用有只有非固定参数的函数的时候我们可以不传参数。

非固定参数分一个*和两个*,*args会把传入的参数变成元祖,**kwargs把传入的参数变成字典,当然*ages可以是别的名称,但是在规范中最好使用*args,和**kwargs#!/usr/bin/env python

# -*- coding:utf-8 -*-

def print_str(*args,**kwargs):

print("我是*",args)

print("我是**",kwargs)

#传入列表

userlist = ["Ben","22","Man"]

print_str(userlist,"America")

print("----------------------------------")

#传入字典

print_str(A = "1",B = "2")

非固定传参

既然形参可以带*和**,那么实参也是可以带*和**,那么*就是配合列表使用的,**就是配合字典的!#!/usr/bin/env python

# -*- coding:utf-8 -*-

def print_str(*args,**kwargs):

print("我是*",args)

print("我是**",kwargs)

#传入列表

userlist = ["Ben","22","Man"]

print_str(*userlist)

print("----------------分隔符----------------")

#传入字典

userdict = {"name":"Ben","age":"022","gender":"Man"}

print_str(**userdict)

解参

实参带*就会把列表分解成 “Ben”,”22″,”Man” 一个一个单独的元素传入函数,而**会把字典分解成name=”Ben”,age=”022″,gender=”Man”

这种键值对传入函数。

形参与实参

形参:

变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用

函数后则不能再使用该形参变量

实参:

可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此

应预先用赋值,输入等办法使参数获得确定值

注!当普通参数和默认参数和非固定参数结合使用的时候,要遵循一个顺序,普通参数在默认参数前面,默认参数在非固定参数前面

返回值

在正常使用函数的时候,函数是可以把函数内部处理的结果返回给函数调用者的,在没有返回值得函数中会保留None传给函数调用者,返回值可以返回序列等

在函数执行的时候遇到return函数会停止执行,并返回结果#!/usr/bin/env python

# -*- coding:utf-8 -*-

#创建函数

def print_str(Age):

if int(Age) <= 30:

return "你才%s啊!真年轻"%(Age)

else:

return "你都%s啦!老家伙"%(Age)

in_age = input("请输入你的年龄:")

word = print_str(in_age)

print(word)

return

嵌套函数

在函数内部也可以写函数,这样就是外层函数套着内侧函数,这种形式称之为嵌套函数,同理因为作用域的关系嵌套函数只能内部调用

return unction_2(stra)+”我是第二层\n” 就等于先 c = unction_2(stra) 然后 return c+”我是第二层\n”def unction(stra):

def unction_2(stra_2):

return stra_2+"我是第三层\n"

return unction_2(stra)+"我是第二层\n"

r_str = unction("")

print(r_str+"我是第一层")

嵌套函数

三、递归

前面已经介绍了函数相关的知识,在函数中,函数可以调用其他的函数,并且函数还可以调用自身,利用这种特性我们可以完成一些特定的

操作,这种函数调用自身的形式就是递归

def recursion() :

return recursion()

在递归中不能像上面两行一样一直调用自身,这样一会程序就会崩溃,因为它永远的在调用就跟while死循环一样出不去,所以递归也需要进

判断给它出口

例子:阶乘

什么是阶乘,阶乘就是给一个自然数N,然后计算N的阶乘那么 N = 1x2x3x4….N ,这个就是阶乘,我们可以把它到过来看,

N = N x (n-1) x (n-2) x (n-3) …… 1 一直乘到括号中的值等于1,既然知道了阶乘是什么,那么我们来写一个程序实现它def factorial(n):

for i in range(1,n):

n *= i

return n

c = factorial(4)

print(c)

阶乘非递归版本

剖析:上面的例子首先把n=4传入进去,然后通过 for i in range(1,4)让i分别等于1,2,3,然后进行 n*=i,我们可以看出这个for循环是循环3次的

第一次(n = n*i) n = 4*1 ,此时n还是等于4

第二次(n = 4*i) n = 4*2 此时n = 8

第三次(n = 8*i) n = 8*3 此时n等于24

此时for循环了3次所以结束了,通过return把n的结果返回,所以最终结果算出 4的阶乘等于24

递归版本

下面看递归版本的阶乘def factorial(n) :

if n == 1:

return 1

else:

return n * factorial(n-1)

c = factorial(4)

print(c)

阶乘递归版本

剖析:

首先c = factorial(4)开始执行函数,然后进行第一次判断 n == 1,显然第一层n不等于1,然后碰到return n * factorial(n-1),碰到return本来是要返回的,但是 factorial(n-1)

有调用了factiorial这个函数,因此进入了第二层

第二层因为上一层传入的参数是n-1,所以第二层的n是等于3的,然后判断,这一层的n也不等于1,然后又进入第三层

第三层n等于3,然后判断这一层的n还不等于1,然后又进入第四层

到第四层的时候这时的 n就等于1,所以触发了 return 1 不再调用函数了,所以就开始返回

返回第三层 return n * factorial(n-1) , 此时factorial(n-1) 就等于第四层return上去的1,所以第三层返回时就等于return n * 1(return 2 * 1),并且第三层n是等于2的

返回第二层factorial(n-1)就等于第三层return上去的2,并且第二层n是等于3的,return 3 * 2

返回第一层factorial(n-1)就等于第二层return上去的6,并且第一层n是等于4的,return 4 * 6

到此为止递归执行完毕,c就等于 4 * 6 c=24

四、匿名函数

匿名函数也叫lambda函数,函数没有具体的名称。语法:function name= lambda args(多个参数用逗号隔开): Expression(表达式,表达式的结果就是返回值)

先来看一个最简单例子:#普通函数

def func(arg1,arg2):

return arg1-arg2

#lambda函数

func_2 = lambda arg1,arg2: arg1-arg2

#传参执行

print(func(5,4))

print(func_2(5,4))

匿名函数

有认识,这个匿名函数和普通函数没有什么区别么,其实匿名函数就像三元运算一样,并且能够用lambda函数有几大优势

1、在一些不会再别的地方调用的函数,我们可以使用匿名函数,并且这样简化了代码,看起来更加整洁。

2、lambda函数将会搭配一些内置函数来使用(下面会涉及到)

五、闭包

在上面的示例中知道了函数可以调用函数本身,这种形式称之为递归,那么还可以将函数作为参数返回,这种形式就称之为闭包

闭包最大的好处就是即用即调,闭包对于安装计算,隐藏状态,以及在函数对象和作用域中随意地切换是很有用的!#!/usr/bin/env python

# -*- coding:utf-8 -*-

def func(rate):

count = [0]

def add_func(arg):

count[0] +=1

print("第%s次调用"%count[0])

arg = arg - arg*rate

return arg

return add_func

closure = func(0.03)

print(closure(1000))

print(closure(1100))

print(closure(1200))

闭包示例

例子中做了一个减去手续费后返回余额的功能,首先执行了func函数,将利率封装了进去,然后,func函数把它内部的函数进行了进行了返回

要知道当函数不加括号的时候是不执行的!,所以此时closoure就是 add_func 函数的内存地址,当想要使用这个功能的时候,直接把closoure加括号

并传入值即可执行。并且可以看到的是在全局作用域中执行,随时可以切换到局部作用域。

六、高阶函数

函数可以用来当做返回值,可以用调用自己本身,高阶函数就是函数的参数把另一个函数作为参数,这种函数就称之为高阶函数。def func_1(num):

return num+1

def func_2(num):

return num-1

def func_main(num,func):

# 可以简写成return func(num)

results = func(num)

return results

results = func_main(10,func_1)

print(results)

print(func_main(10,func_2))

高阶函数

编写高阶函数,就是让函数的参数能够接收别的函数。

七、内置函数

内置函数就是python中内置的一些方法

内置函数使用方法示例,详细介绍请参考# !/usr/bin/env python

# -*- coding:utf-8 -*-

#返回数字的绝对值。 参数可以是整数或浮点数。 如果参数是复数,则返回其大小。

print(abs(-1.11))

#传入一个可被循环的元素,如果这个元素中有一个为False则都为假

# 0 空值 False 都为假

print(all([1,2,3]))

#与all相反,只有一个为真,则为真;

print(any([0,2,False]))

#这个函数跟repr()函数一样,返回一个可打印的对象字符串方式表示。当遇到非ASCII码时

#就会输出\x,\u或\U等字符来表示。与Python 2版本里的repr()是等效的函数。

print(ascii("dsads"),ascii(66),ascii('b\23'))

#将十进制转换为二进制;

print(bin(10))

#返回布尔值,即True或False之一,如果参数为false或省略,则返回False; 否则返回True。

print(bool(1))

#根据传入的参数创建一个新的字节数组

#如果传入字符串必须给出编码

print(bytearray('你好','utf-8'))

#当source参数是一个可迭代对象,那么这个对象中的元素必须符合大于0 小于256

print(bytearray([256,1,2]))

#返回一个的“bytes”对象,返回bytes类型

bytes('中文','utf-8')

#检查对象是否可以被调用

def func():

pass

print(callable(func))

#返回整数所对应的Unicode字符,chr(97)返回字符串'a',而chr(8364)返回字符串'€'。

print(chr(126))

#是用来指定一个类的方法为类方法,类方法可以不实例化直接调用

class A:

@classmethod

def B(cls,arg1,):

print(arg1)

A.B(1)

A().B(1)

#将源编译为代码或者AST对象。代码对象能够通过exec语句来执行或者eval()进行求值。

#源可以是正常字符串,字节字符串或AST对象。

expr = "5+5-1"

obj = compile(expr,"","eval")

print(eval(obj))

#返回值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数。

print(complex(1, 2))

print(complex(1))

print(complex("1+2j"))

# 参数是一个对象和一个字符串。 该字符串必须是对象属性之一的名称。

class A:

def a1(self):

print("a1")

def a2(self):

print("a2")

obj = A

print(dir(obj))

delattr(obj, "a1")

print(dir(obj))

#dir 返回对象中的方法

strs="aaa"

print(dir(strs))

#返回两个数值的商和余数

print(divmod(7,3))

#用于遍历序列中的元素以及它们的下标

print(enumerate([1,2,3]))#返回的是可迭代的对象

for i,j in enumerate(('A','B','C')):

print(i,j)

#将字符串str当成有效的表达式来求值并返回计算结果。

print(eval("1+2+3"))

print(eval("False or True"))

#字符串str当成动态语句块执行并返回结果

exec('a=1+2+3')

print(a)

#使用指定方法(方法,函数),过滤可迭代对象的元素

def add(arg):

return arg > 3

for i in filter(add,[1,2,3,4,5]):

print(i)

#浮点型

print(float(11))

#格式化显示 更多方法请参考官方说明

print('{:,.2f}'.format(111111))

#根据传入的参数创建一个新的不可变集合

a = frozenset([1,2,3,4,5])

print(a)

#获取对象的属性值

class A():

def __init__(self,):

self.name = "123"

b = A()

print(getattr(b,'name'))

#返回当前作用域内的全局变量和其值组成的字典

print(globals())

#检查对象是否含有属性

class A():

def __init__(self,):

self.name = "123"

b = A()

print(hasattr(b,'name'))

#哈希值计算

#在当前环境中是唯一的

print(hash('Hello'))

#help帮助

def funcs(args):

"""

Function description

:param args: args = list

:return:

"""

pass

print(help(funcs))

#转换16进制

print(hex(44))

#显示对象的标识符

print(id("123"))

#input标准输入

s = input("user name:")

print(s)

#int返回整数

print(int(1.2))

print(int("2"))

#判断对象是否是类或者类型元组中任意类元素的实例

print(isinstance("1",int))

print(isinstance(1.1,(int,float)))

#判断类是否是另外一个类或者类型元组中任意类元素的子类

print(dir(str))

print(issubclass(bytearray,str))

print(issubclass(bool,int))

#根据传入的参数创建一个新的可迭代对象

a = iter('12345')

print(next(a))

print(next(a))

#返回对象的长度len

a = [1,2,3,4]

#转换列表

print(list("abcd"))

#返回当前作用域内的局部变量和其值组成的字典

def A():

print(locals())

s = 1

print(locals())

A()

#使用指定方法去作用传入的每个可迭代对象的元素,生成新的可迭代对象

def add(x):

return x+100

lists = [1,2,3,4]

for i in map(add,lists):

print(i)

#max:返回最大值

print(max(1,2,3))

print(max([1,2,3,4]))

#在进行切片并赋值数据时,不需要重新copy原列表数据,可以直接映射原数据内存;

s = memoryview(b'abcd')

print(s[1])

#返回最小值

print(min(1,2,3))

print(min([2,3]))

#返回可迭代对象中的下一个元素值

a = iter('1234')

print(next(a))

#创建一个新的object对象(新式类)

class B(object):

pass

#转化成8进制数字符串

print(oct(10))

#open文件操作

file = open('test.txt',encoding="utf-8")

#ord:返回Unicode字符对应的整数

print(ord("A"))

#幂运算

print(pow(2,3))

#标准输出

print()

#property:标示属性的装饰器

#类中使用具体方法请百度,或者等待后续更新

property

#range:根据传入的参数创建一个新的range对象

range(10)

range(1,10)

"""repr()函数得到的字符串通常可以用来重新获得该对象,repr()的输入对python比较友好。

通常情况下obj==eval(repr(obj))这个等式是成立的。"""

obj='Python'

print(eval(repr(obj)))

#翻转序列

a = reversed([1,2,3,4,5])

print(list(a))

#round:对浮点数进行四舍五入求值

print(round(1.5))

#set 转换成集合

print(set([1,2,3]))

#setattr:设置对象的属性值

class A():

def __init__(self,age):

self.age = age

s = A(11)

print(s.age)

setattr(s,'age',22)

print(s.age)

#根据传入的参数创建一个新的切片对象

c1 = slice(3)

c2 = slice(2,4)

c3 = slice(0,5,2)

s = [1,2,3,4,5,6]

print(s[c1])

print(s[c2])

print(s[c3])

#排序,返回一个新的列表默认按字符ascii码排序

a = [4,3,2,1,7]

print(sorted(a))

#标示方法为静态方法的装饰器

class B(object):

def __init__(self,age):

self.age = age

@staticmethod

def hello(args):

print(args)

B.hello("Hello World")

#字符串类型

print(str(123))

#求和

print(sum([1,2,3,4]))

#根据传入的参数创建一个新的子类和父类关系的代理对象

class A(object):

def __init__(self):

print("我是 A Clase")

class B(A):

def __init__(self):

print("我是 B Class")

super().__init__()

b = B()

#元祖

tuple([1,2,3,4])

#type 返回对象的类型

print(type([1]))

print(type("1"))

#返回当前作用域内的局部变量和其值组成的字典,或者返回对象的属性列表

def func():

print(vars())

s = 1

print(vars())

func()

#聚合传入的每个迭代器中相同位置的元素,返回一个新的元组类型迭代器

list1 = [1,2,3]

list2 = ["A","B","C","D"]

print(zip(list1,list2))

for i in zip(list1,list2):

print(i)

#__import__:动态导入模块

__import__

更多简学Python第三章__函数式编程、递归、内置函数 相关文章请关注PHP中文网!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值