我的Python函数与函数式编程

python函数与函数式编程

1、介绍

1、面向对象:--->---> class定义															#编程的规范
2、面向过程:---> 过程 ---> def定义 --> 将一段段的逻辑和过程包含到由一个def定义的过程中,return
3、函数式编程:---> 函数 ---> def定义,return
函数的优点:代码重用、保持一致性、可扩展性
区别:面向过程实际上就是没有返回值的函数

2、函数

编程语言中函数的定义:函数式逻辑结构化和过程化的一种编程方法。
def test(x):
    "The function definitions"
    x+=1
    return x

def:	定义函数的关键字
test:	函数名
():		内可定义形参
"":		文档描述(非必要,但建议为函数添加描述信息)
x+=1:	泛指代码块或程序处理逻辑
return:	定义返回值
例子1、
def logger():
    with open("a.txt","a+",encoding = "utf-8") as f:
        f.write('end action\n')
def test1():
    print("in the test1")
    logger()
def test2():
    print("in the test2")
    logger()
def test3():
    print("in the test3")
    logger()
test1()
test2()
test3()

---> 
in the test1
in the test2
in the test3
	---> #cat a.txt
	end action
	end action
	end action
例子2、加入时间模块
import time

def logger():
    time_format = '%Y-%m-%d %X'								#%Y-%m-%d(年月日),%X(::)
    time_current = time.strftime(time_format)				#按照上面的时间格式调用
    with open("a.txt","a+",encoding = "utf-8") as f:
        f.write('%s end action\n'%time_current)

def test1():
    print("in the test1")
    logger()
def test2():
    print("in the test2")
    logger()
def test3():
    print("in the test3")
    logger()
test1()
test2()
test3()

---> 
in the test1
in the test2
in the test3
	---> #cat a.txt
	2019-09-06 14:03:45 end action
	2019-09-06 14:03:45 end action
	2019-09-06 14:03:45 end action
例子3、关于函数的return
def test1():
    print("in the test1")
    return 0
x = test1()											#x就代表test1函数体中return返回的结果
print(x)

--->
in the test1
0
例子4、有return和无return的区别
def test1():
    print("in the test1")
    
def test2():
    print("in the test2")
    return 0
def test3():
    print("in the test3")									#返回值可以是任意的数据类型,多的话返回一个元组
    return 1,['lishang','zhaoxiaomeng'],{'lishang':'zhaoxiaomeng'},'zxm love ls'
x = test1()
y = test2()
z = test3()
print(x)			#test1没有return,返回值将为空(None)
print(y)			#y=0
print(z)			#z=(1, ['lishang', 'zhaoxiaomeng'], {'lishang': 'zhaoxiaomeng'}, 'zxm love ls')

--->
in the test1
in the test2
in the test3
None
0
(1, ['lishang', 'zhaoxiaomeng'], {'lishang': 'zhaoxiaomeng'}, 'zxm love ls')
总结:
  返回值数=0,返回None
  返回值数=1,返回object
  返回值数>1,返回一个tuple
例子5、关键字参数不能在未知参数之前
def test(x,y):          			#x,y是形参
    print(x)
    print(y)

test(3,2)               			#位置参数调用,实参与形参一一对应
test(y=3,x=4)           			#关键字调用,与形参顺序无关
test(1,y=2)             			#两种混合,关键字调用必须在后面
test(x=1,2)							#这种方式会报错,关键字参数不能在位置参数的前()
例子6、默认参数
def test(x,y=2):
    print(x)
    print(y)

test(1)					#y不赋值,用默认的y=2赋给y
test(1,2)				#全都赋值,引用手动赋值的12
test(1,3)				#也可以改变,引用手动赋值的13
例子7、多个实参
*args接收N个位置参数,转换成元组的形式
**kwargs接收N个关键字参数,转换成字典的方式

def test(*args):										#*args代表接收的实参数目不固定,转换成元组的形式
    print(args)

test(1,2,3,4,5)
test(*[1,2,3,4,5,])    									 #也可以按照*[]*跟元组的方式传递

--->
(1, 2, 3, 4, 5)
(1, 2, 3, 4, 5)

-----------------------------也可以 test1(x,*args混合接收)----------------------------
def test1(x,*args):
    print(x)
    print(args)

test1(1, 2, 3, 4, 5, 6, 7)

--->
1
(2, 3, 4, 5, 6, 7)

----------------------------还可以 test2(**kwargs)接收接收N个关键字参数--------------------
def test2(**kwargs):
	print(kwargs)
test2(name='lishang',age=23,sex='man')
test2(**{'name':'xiaomeng','age':18,'sex':'girl'})     #也可以按照**{}**跟字典的方式传递

--->
{'name': 'lishang', 'age': 23, 'sex': 'man'}
{'name': 'xiaomeng', 'age': 18, 'sex': 'girl'}

-----------------------还可以 test3(name,**kwargs)位置参数与关键字参数混合接收----------------
def test3(name, **kwargs):
    print(name)
    print(kwargs)

test3('lishang',age=18,girlfriend='zhaoxiaomeng')
lishang
{'age': 18, 'girlfriend': 'zhaoxiaomeng'}
--->
lishang
{'age': 18, 'girlfriend': 'zhaoxiaomeng'}

-----------------------还可以 test4(name,age=18,**kwargs)字典与默认参数混合接收----------------
def test4(name,age=18,**kwargs):
    print(name)
    print(age)
    print(kwargs)

test4('xiaomeng', sex='girl', hobby='lishang')

--->
xiaomeng
18
{'sex': 'girl', 'hobby': 'lishang'}

----------------最后可以 test5(name,age=18,*args,**kwargs)形参、默认参数、元组、字典混合接收:-----------
def test5(name,age=18,*args,**kwargs):
	print(name)
	print(age)
	print(args)
	print(kwargs)
test5('xiaomeng',24,'she likes Lishang',sex='girl',hobby='lishang')

--->
xiaomeng
24
('she likes Lishang',)
{'sex': 'girl', 'hobby': 'lishang'}

3、局部变量和全局变量

3.1、局部变量
#函数第三行的(name)就是局部变量,只在局部生效
def change_name(name):
    print("before name:",name)
    name = "LiShang"					#这个函数是这个变量的作用域,这里改变的name只在函数中生效
    print("after name:",name)

name = "lishang"
change_name(name)	
print("name:",name)						#因此哪怕函数中已经改为了大写,最后输出的还是小写

--->
before name: lishang
after name: LiShang						#只改变了函数中的变量
name: lishang							#输出与一开始一致
3.2、全局变量
#函数中的(school)是局部变量,只影响函数中他自己
#最外层定义的(school)是全局变量,函数中的school改变,它不会变

school = "old boy"								#全局变量
def change_name(name):
    school = "baoge edu"						#局部变量
    print("before name:",name,school)
    name = "LiShang"
    print("after name:",name)

name = "lishang"
change_name(name)
print("name:",name)
print(school)

--->
before name: lishang baoge edu					#这里输出的是函数中局部变量(school)的值
after name: LiShang
name: lishang
old boy											#这里输出的是最外层全局变量的值
3.3、如果要在局部改全局变量,添加—global------但是不要用这种方式
school = "old boy"								#全局变量
def change_name(name):
	global school								#加上这个,在局部可修改全局变量
    school = "baoge edu"						#局部变量
    print("before name:",name,school)
    name = "LiShang"
    print("after name:",name)

name = "lishang"
change_name(name)
print("name:",name)
print(school)

--->
before name: lishang baoge edu
after name: LiShang
name: lishang
baoge edu										#这次就输出了局部变量中(school)的值
3.4、总结—局部改全局变量
字符串、数字、字母等数据类型不能在局部修改全局变量
列表、字典、集合、类都是可以再局部修改全局变量的

4、递归

在函数内部,可以调用其他函数。如果一个函数在内部调用自己,这个函数就叫递归函数
def calc(n):
    print(n)
    return calc(n+1)

calc(0)``

--->
1
2
3
...
995
RecursionError: maximum recursion depth exceeded while calling a Python object
当调用python的时候,超出了最大的递归深度,内部保护机制,最大深度为999
4.1实例、输入一个数字,每次除以2,知道小于1,就停止
def calc(n):
    print(n)
    if int(n/2) >0:
        return calc(int(n/2))
    print("+++++++>",n)

calc(10)

--->
10
5
2
1
+++++++> 1
递归的特性:
1、必须有一个明确的结束条件
2、每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3、递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个
   函数调用,栈就会增加一层栈帧,每当函数返回,栈就会减一层栈帧.由于栈的大小不是无限的,所以,递归调用的次数过
   多,会导致溢出)

5、函数式编程

   函数是Python内建支持的一种封装,我们通过把大段的代码拆成函数,通过一层一层的函数调用,就可以把复杂的任务
分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的圣墟设计单元。
   而函数式编程(多了一个'式')--Functional Programming,虽然也可以递归到面向过程的程序设计,但其思想更
接近数学计算,函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变
量的映射。也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态。比如sqrt(x)函数计算x的平方根,只要x不变,
不论什么时候调用,调用几次,值都是不变的。
   Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
一、定义
   简单说,"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。主要思想是
把运算过程尽量写成一系列嵌套的函数调用。
   举例来说,现在有这样一个数学表达式:
  (1 + 2) * 3 - 4
传统的过程式编程,可能这样写:
  var a = 1 + 2;
  var b = a * 3;
  var c = b - 4;
函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,然后写成下面这样:
  var result = subtract(multiply(add(1,2), 3), 4);
这段代码再演进以下,可以变成这样
add(1,2).multiply(3).subtract(4)
这基本就是自然语言的表达了。再看下面的代码,大家应该一眼就能明白它的意思吧:
merge([1,2],[3,4]).sort().search("2")
因此,函数式编程的代码更容易理解。
要想学好函数式编程,不要玩py,玩Erlang,Haskell, 好了,我只会这么多了。。。

6、高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def add(x,y,f):
    return f(x) + f(y)
 
res = add(3,-6,abs)									#abs()函数是取绝对值函数
print(res)

--->
9
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值