Python 函数
Python 函数
Python 函数之定义函数
在Python中,定义一个函数要使用
- def语句,依次写出函数名、括号、括号中的参数和冒号:
- 然后,在缩进块中编写函数体,函数的返回值用return语句返回。
1、定义一个函数
def myfirst():
print("Hello world!")
myfirst()
#输出结果
Hello world!
2、定义发送邮件的函数
- 不接收用户指定邮箱
# 不接收用户指定邮箱的函数
#!/usr/bin/env python
# -*- conding:utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
def mail():
msg = MIMEText('邮件内容', 'plain', 'utf-8')
msg['From'] = formataddr(["evescn", '18111434862@163.com'])
msg['To'] = formataddr(["gmkk", '519518995@qq.com'])
msg['Subject'] = "主题"
server = smtplib.SMTP("smtp.163.com", 25)
server.login("18111434862@163.com", "XXXXXX")
server.sendmail('18111434862@163.com', ['519518995@qq.com', ], msg.as_string())
server.quit()
mail()
- 用户可以指定邮箱
# 用户可以指定邮箱的函数
#!/usr/bin/env python
# -*- conding:utf-8 -*-
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
def mail(mails):
msg = MIMEText('邮件内容', 'plain', 'utf-8')
msg['From'] = formataddr(["evescn", '18111434862@163.com'])
msg['To'] = formataddr(["gmkk", mails])
msg['Subject'] = "主题"
server = smtplib.SMTP("smtp.163.com", 25)
server.login("18111434862@163.com", "XXXXXX")
server.sendmail('18111434862@163.com', [mails, ], msg.as_string())
server.quit()
mail('519518995@qq.com')
3、函数的参数个数
- 无参
- 一个参数
- 两个参数
- ……
- 动态参数
4、举例
- 无参函数
# 无参函数
def show():
print('a')
return [11, 22, ]
print('b')
show()
# 输出结果
a
- 一个参数
# 一个参数
def show(arg):
print(arg)
n = [11, 22, 33, 44]
show(n)
# 输出结果
[11, 22, 33, 44]
- 两个参数
# 两个参数
def show(arg, xxx):
print(arg, xxx)
show('evescn', 'gmkk')
# 输出结果
evescn gmkk
- 默认参数
# 默认参数,必须写在实参之后
def jiecheng(arg, n=2):
print(arg ** n)
jiecheng(2)
jiecheng(2, 3)
# 输出结果
4
8
- 指定参数
# 指定参数
def show(a1,a2):
print(a1,a2)
show(123, 999)
show(a2=123, a1=999)
# 输出结果
123 999
999 123
- 动态参数列表
# 动态参数
# 传入参数为列表 OK?
def show(*arg): # 把所有位置参数转为了元组
print(arg, type(arg))
show(1,2,3,4,5,6,7,8)
# 输出结果
(1, 2, 3, 4, 5, 6, 7, 8) <class 'tuple'>
- 动态参数字典
# 动态参数
# 传入参数为字典 OK?
def show(**arg): # 把所有关键字参数转为了字典
print(arg,type(arg))
show(n1=1,n2=2,n3=3,n4=4,)
# 输出结果
{'n4': 4, 'n3': 3, 'n1': 1, 'n2': 2} <class 'dict'>
- 动态参数
# 实参、一个*的动态参数、两个*的动态参数
# 定义是先放变量,在放一个*的参数,再放**的参数
def show(a1, *args, **kwargs):
print(a1)
print(args, type(args))
print(kwargs, type(kwargs))
show(11, 22, 33, 44, n1=99, n2=88, n3=77)
# 输出结果
11
(22, 33, 44) <class 'tuple'>
{'n3': 77, 'n1': 99, 'n2': 88} <class 'dict'>
- 动态参数,传入数据类型列表和字典
# 仔细对比2次的输出结果,对于创建的列表和字典,传给函数时需指定传递给那个变量
def show(*args, **kwargs):
print(args,type(args))
print(kwargs, type(kwargs))
a1=[11, 22, 33, 44]
a2={'n1': 99, 'n2': 88, 'n3': 77}
show(a1, a2)
show(*a1, **a2)
#输出结果
([11, 22, 33, 44], {'n3': 77, 'n2': 88, 'n1': 99}) <class 'tuple'>
{} <class 'dict'>
(11, 22, 33, 44) <class 'tuple'>
{'n3': 77, 'n2': 88, 'n1': 99} <class 'dict'>
- format函数
# format函数,如何给farmat函数传递参数
s1 = "{0} to {1}"
l = ['evescn','gmkk']
ret1 = s1.format(*l)
ret2 = s1.format('evescn','gmkk')
print(ret1)
print(ret2)
s1 = "{name} to {acter}"
l = {'name':'evescn', 'acter':'gmkk'}
ret1 = s1.format(**l)
ret2 = s1.format(name='evescn', acter='gmkk')
print(ret1)
print(ret2)
# 输出结果
evescn to gmkk
evescn to gmkk
evescn to gmkk
evescn to gmkk
Python 函数之函数调用
Python内置了很多有用的函数,我们可以直接调用。
要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数。可以直接从Python的官方网站查看文档:
http://docs.python.org/3/library/functions.html#abs
也可以在交互式命令行通过help(abs)
查看abs
函数的帮助信息。
1、调用abs函数
>>> abs(100)
100
>>> abs(-20)
20
>>> abs(12.34)
12.34
2、数据类型转换
Python内置的常用函数还包括数据类型转换函数,比如int()函数可以把其他数据类型转换为整数:
>>> int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> str(100)
'100'
>>> bool(1)
True
>>> bool('')
False
3、函数名
函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”
>>> a = abs # 变量a指向abs函数
>>> a(-1) # 所以也可以通过a调用abs函数
1
4、内置函数
注:查看详细猛击这里
局部变量全局变量
1、全局与局部变量
name = "Evescn"
def change_name(name):
print("before change:",name)
name = "GMKK"
print("after change", name)
change_name(name)
print("name: ",name)
# 输出结果
before change: Evescn
after change GMKK
name: Evescn
- 在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
- 全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
- 当全局变量与局部变量同名时:
- 在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
Python 函数之递归
1、递归函数定义
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
我们来计算阶乘 n! = 1 x 2 x 3 x ... x n
,用函数 fact(n)
表示
fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n
所以, fact(n)
可以表示为 n x fact(n-1)
,只有 n=1
时需要特殊处理。
于是, fact(n)
用递归的方式写出来就是
def fact(n):
if n==1:
return 1
return n * fact(n - 1)
上面就是一个递归函数。可以试试:
>>> fact(1)
1
>>> fact(5)
120
>>> fact(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L
如果我们计算 fact(5) ,可以根据函数定义看到计算过程如下:
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。可以试试fact(1000):
>>> fact(1000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in fact
...
File "<stdin>", line 4, in fact
RuntimeError: maximum recursion depth exceeded in comparison
2、利用函数编写如下数列
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368 ...
def func(arg1, arg2):
# for i in range(10):
if arg1 == 0:
print(arg1)
print(arg2)
arg3 = arg1 + arg2
if arg3 < 1000:
print(arg3)
func(arg2, arg3)
else:
return
func(0, 1)
# 运行结果
0
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
转载自
https://www.liaoxuefeng.com/wiki/1016959663602400/1017268131039072
高阶函数
什么是高阶函数?下面条件满足一个即时高阶函数
- 把一个函数名当作实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
- 函数返回值中包含函数名(不修改函数的调用方式)
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
def add(x,y,f):
return f(x) + f(y)
res = add(3,-6,abs)
print(res)
函数返回值中包含函数名
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
当我们调用 lazy_sum()
时,返回的并不是求和结果,而是求和函数:
>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function lazy_sum.<locals>.sum at 0x101c6ed90>
调用函数 f
时,才真正计算求和的结果:
>>> f()
25
Python 函数之lambda、map、filter和reduce
1、lambda 函数
lambda()是Python里的匿名函数,其语法如下:
lambda [arg1[, arg2, ... argN]]: expression
学习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即:
# 普通条件语句
if 1 == 1:
name = 'evescn'
else:
name = 'gm'
# 三元运算
name = 'evescn' if 1 == 1 else 'gm'
对于简单的函数,也存在一种简便的表示方式,即:lambda表达式
# ###################### 普通函数 ######################
# 定义函数(普通方式)
def func(arg):
return arg + 1
# 执行函数
result = func(123)
# ###################### lambda ######################
# 定义函数(lambda表达式)
my_lambda = lambda arg : arg + 1
# 执行函数
result = my_lambda(123)
lambda存在意义就是对简单函数的简洁表示,下面在举一个列表的例子
l = [11, 22, 33, 44]
new_l = map(lambda x: x + 10, l)
a = list(new_l)
print(a)
# 输出结果
[21, 32, 43, 54]
2、map 函数
map函数会根据提供的函数对指定序列做映射,其语法如下:
map(function, sequence[, sequence, ...])
map 函数会对序列参数 sequence 中的每个元素调用 function 函数,返回的结果为每一个元素调用function函数的返回值
l = [11, 22, 33, 44]
def myadd(x):
return x + 10
new_n = map(myadd, l)
b = list(new_n)
print(b)
# 输出结果
[21, 32, 43, 54]
利用map()
函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT']
,输出:['Adam', 'Lisa', 'Bart']
:
# -*- coding: utf-8 -*-
def normalize(str):
return str.capitalize()
# 测试:
L1 = ['adam', 'LISA', 'barT', 'ROOT']
L2 = list(map(normalize, L1))
print(L2)
# 输出结果
['Adam', 'Lisa', 'Bart', 'Root']
3、filter 函数
filter函数会根据提供的函数对指定序列做筛选,其语法如下:
filter(function, iterable)
filter 函数会对于序列中的元素进行筛选,最终获取符合条件的序列
def myfunc(x):
if x > 30:
return True
else:
return False
a = [11, 22, 33]
new_a = filter(myfunc,a)
b = list(new_a)
print(b)
# 输出结果
[33]
4、reduce 函数
对于序列内所有元素进行累计操作
reduce
把一个函数作用在一个序列 [x1, x2, x3, ...]
上,这个函数必须接收两个参数, reduce
把结果继续和序列的下一个元素做累积计算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比方说对一个序列求和,就可以用 reduce
实现:
>>> from functools import reduce
>>> def add(x, y):
... return x + y
...
>>> reduce(add, [1, 3, 5, 7, 9])
25
当然求和运算可以直接用Python内建函数 sum()
,没必要动用 reduce
。
但是如果要把序列 [1, 3, 5, 7, 9]
变换成整数 13579
, reduce
就可以派上用场:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579
这个例子本身没多大用处,但是,如果考虑到字符串 str
也是一个序列,对上面的例子稍加改动,配合 map()
,我们就可以写出把 str
转换为 int
的函数
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> def char2num(s):
... return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
...
>>> reduce(fn, map(char2num, '13579'))
13579
整理成一个 str2int
的函数就是:
from functools import reduce
def str2int(s):
def fn(x, y):
return x * 10 + y
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
return reduce(fn, map(char2num, s))
还可以用 lambda
函数进一步简化成:
from functools import reduce
def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
def str2int(s):
return reduce(lambda x, y: x * 10 + y, map(char2num, s))
也就是说,假设Python没有提供 int()
函数,你完全可以自己写一个把字符串转化为整数的函数,而且只需要几行代码!
转载自
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317852443934a86aa5bb5ea47fbbd5f35282b331335000
http://www.cnblogs.com/wupeiqi/articles/4943406.html
Python 函数之装饰器
1、函数
#### 第一波 ####
def foo():
print 'foo'
foo #表示是函数
foo() #表示执行foo函数
#### 第二波 ####
def foo():
print 'foo'
foo = lambda x: x + 1
foo() # 执行下面的lambda表达式,而不再是原来的foo函数,因为函数 foo 被重新定义了
2、需求
初创公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能。业务部门使用基础功能时,只需调用基础平台提供的功能即可。如下:
############### 基础平台提供的功能如下 ###############
def f1():
print 'f1'
def f2():
print 'f2'
def f3():
print 'f3'
def f4():
print 'f4'
############### 业务部门A 调用基础平台提供的功能 ###############
f1()
f2()
f3()
f4()
############### 业务部门B 调用基础平台提供的功能 ###############
f1()
f2()
f3()
f4()
目前公司有条不紊的进行着,但是,以前基础平台的开发人员在写代码时候没有关注验证相关的问题,即:基础平台的提供的功能可以被任何人使用。现在需要对基础平台的所有功能进行重构,为平台提供的所有功能添加验证机制,即:执行功能前,先进行验证。
写代码要遵循开发封闭原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现的功能代码不允许被修改,但可以被扩展,即:
- 封闭:已实现的功能代码块
- 开放:对扩展开发
如果将开放封闭原则应用在上述需求中,那么就不允许在函数 f1 、f2、f3、f4的内部进行修改代码
def w1(func):
def inner():
# 验证1
# 验证2
# 验证3
return func()
return inner
@w1
def f1():
print 'f1'
@w1
def f2():
print 'f2'
@w1
def f3():
print 'f3'
@w1
def f4():
print 'f4'
对于上述代码,也是仅仅对基础平台的代码进行修改,就可以实现在其他人调用函数 f1 f2 f3 f4 之前都进行【验证】操作,并且其他业务部门无需做任何操作。
这段代码的内部执行原理是什么呢?
单独以f1为例:
def w1(func):
def inner():
# 验证1
# 验证2
# 验证3
return func()
return inner
@w1
def f1():
print 'f1'
当写完这段代码后(函数未被执行、未被执行、未被执行),python解释器就会从上到下解释代码,步骤如下:
- def w1(func): ==>将w1函数加载到内存
- @w1
没错,从表面上看解释器仅仅会解释这两句代码,因为函数在没有被调用之前其内部代码不会被执行。
从表面上看解释器着实会执行这两句,但是 @w1
这一句代码里却有大文章,@函数名
是python的一种语法糖。
如上例@w1内部会执行一下操作:
- 执行w1函数,并将 @w1 下面的 函数 作为w1函数的参数,即:@w1 等价于 w1(f1)
所以,内部就会去执行:
def inner:
#验证
return f1() # func是参数,此时 func 等于 f1
return inner # 返回的 inner,inner代表的是函数,非执行函数
其实就是将原来的 f1 函数塞进另外一个函数中
- 将执行完的 w1 函数返回值赋值给@w1下面的函数的函数名
w1函数的返回值是:
def inner:
#验证
return 原来f1() # 此处的 f1 表示原来的f1函数
然后,将此返回值再重新赋值给 f1,即:
新f1 = def inner:
#验证
return 原来f1()
所以,以后业务部门想要执行 f1 函数时,就会执行 新f1 函数,在 新f1 函数内部先执行验证,再执行原来的f1函数,然后将 原来f1 函数的返回值 返回给了业务调用者。
如此一来, 即执行了验证的功能,又执行了原来f1函数的内容,并将原f1函数返回值 返回给业务调用着
3、装饰器参数
- 一个参数
### 一个参数
def w1(func):
def inner(arg):
# 验证1
# 验证2
# 验证3
return func(arg)
return inner
@w1
def f1(arg):
print 'f1'
- 两个参数
### 两个参数
def w1(func):
def inner(arg1,arg2):
# 验证1
# 验证2
# 验证3
return func(arg1,arg2)
return inner
@w1
def f1(arg1,arg2):
print 'f1'
- 三个参数
### 三个参数
def w1(func):
def inner(arg1,arg2,arg3):
# 验证1
# 验证2
# 验证3
return func(arg1,arg2,arg3)
return inner
@w1
def f1(arg1,arg2,arg3):
print 'f1'
- 装饰具有处理n个参数的函数的装饰器
### 装饰具有处理n个参数的函数的装饰器
def w1(func):
def inner(*args,**kwargs):
# 验证1
# 验证2
# 验证3
return func(*args,**kwargs)
return inner
@w1
def f1(arg1,arg2,arg3):
print 'f1'
- 装饰具有处理n个参数的函数的装饰器
### 装饰具有处理n个参数的函数的装饰器
def login(func):
def inner(*args, **kwargs):
print("passed user bingo")
return func(*args, **kwargs)
return inner
@login
def home():
print("Welcome to home page!")
@login
def tv(name):
print("Welcome %s to tv page!" %name)
return "gmkk"
@login
def movie(name, age):
print("Welcome %s %s to child page" %(name, age))
home()
t = tv("evescn")
print("T value ", t)
movie("evescn", 15)
# 输出结果
passed user bingo
Welcome to home page!
passed user bingo
Welcome evescn to tv page!
T value gmkk
passed user bingo
Welcome evescn 15 to child page
- 一个函数被多个装饰器装饰
### 一个函数被多个装饰器装饰
def w1(func):
def inner(*args,**kwargs):
# 验证1
# 验证2
# 验证3
return func(*args,**kwargs)
return inner
def w2(func):
def inner(*args,**kwargs):
# 验证1
# 验证2
# 验证3
return func(*args,**kwargs)
return inner
@w1
@w2
def f1(arg1,arg2,arg3):
print 'f1'
- 更吊的装饰器
### 还有什么更吊的装饰器吗?
#!/usr/bin/env python
#coding:utf-8
def Before(request,kargs):
print 'before'
def After(request,kargs):
print 'after'
def Filter(before_func,after_func):
def outer(main_func):
def wrapper(request,kargs):
before_result = before_func(request,kargs)
if(before_result != None):
return before_result;
main_result = main_func(request,kargs)
if(main_result != None):
return main_result;
after_result = after_func(request,kargs)
if(after_result != None):
return after_result;
return wrapper
return outer
@Filter(Before, After)
def Index(request,kargs):
print 'index'
def before1(*request, **kargs):
print("Before")
def after1(*request, **kargs):
print("After")
# def Filter(before_func, after_func):
# def login(main_func):
# def inner(*args, **kwargs):
# before_func()
# print("passed user bingo")
# main_func(*args, **kwargs)
# after_func()
# # return func(*args, **kwargs)
# return inner
# # return func
# return login
def Filter(before_func, after_func):
def outer(main_func):
def wrapper(*request, **kargs):
before_result = before_func(*request, **kargs)
if (before_result != None):
return before_result
main_result = main_func(*request, **kargs)
if (main_result != None):
return main_result
after_result = after_func(*request, **kargs)
if (after_result != None):
return after_result
return wrapper
return outer
@Filter(before1, after1)
def home():
print("Welcome to home page!")
@Filter(before1, after1)
def tv(name):
print("Welcome %s to tv page!" %name)
return "gmkk"
def movie(name):
print("Welcome %s to movie page" %name)
@Filter(before1, after1)
def child(name, age):
print("Welcome %s %s to child page" %(name, age))
home()
t = tv("evescn")
print(t)
child("evescn", 15)
# 输出结果
Before
Welcome to home page!
After
Before
Welcome evescn to tv page!
gmkk
Before
Welcome evescn 15 to child page
After
4、functools.wraps
上述的装饰器虽然已经完成了其应有的功能,即:装饰器内的函数代指了原函数,注意其只是代指而非相等,原函数的元信息没有被赋值到装饰器函数内部。例如:函数的注释信息
### 无元信息
def outer(func):
def inner(*args, **kwargs):
print(inner.__doc__) # None
return func()
return inner
@outer
def function():
"""
asdfasd
:return:
"""
print('func')
function()
# 输出结果
None
func
如果使用@functools.wraps装饰装饰器内的函数,那么就会代指元信息和函数
### 含元信息
import functools
def outer(func):
@functools.wraps(func)
def inner(*args, **kwargs):
print(inner.__doc__) # None
return func()
return inner
@outer
def function():
"""
asdfasd
:return:
"""
print('func')
function()
# 输出结果
asdfasd
:return:
func
转载自
http://www.cnblogs.com/wupeiqi/articles/4980620.html