这一节来学习Python的函数使用。首先看看函数的基本组成,然后学习不同种类的参数传递,以及Python的内置函数。
定义函数的时候,需要包括以下几个部分:
-
def:表示函数的关键字
-
函数名:函数的名称,日后根据函数名调用函数
-
函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
-
参数:为函数体提供数据
-
返回值:当函数执行完毕后,可以给调用者返回数据。可以返回任何数据,一旦返回数据,则函数自动结束,后面的代码不会再执行,如果不主动定义返回值,则默认返回值为None
例子
1
2
3
4
5
6
7
8
|
def
sendmail():
try
:
pass
except
:
return
"Failed"
else
:
return
"Succesful"
ret
=
sendmail()
|
执行函数的时候注意函数声明必须在前面,调用在后面,Python是按顺序操作的,而java,c#是直接把整个文件放内存,因此调用函数的位置无关紧要
小技巧:如果需要测试,可以在Pycharm里面执行断点和debug进行一步步跟踪
接下来看看具体参数是怎么传递的,Python里面有下面几种情况
-
普通参数
-
默认参数,可以在定义的时候给一个预分配的值,但是这个默认参数必须放在末尾
-
动态参数
-
动态参数 *args 和 **args
* 默认将传入的参数,全部放在元组中,元组的元素按顺序传入的值,比如 f1(*[1,2,3,4])
** 默认将传入的参数,全部放在字典中 f1(**{'k1':'v1','k2':'v2'})
例子(默认参数,指定参数)
定义函数send,里面有3个参数,最后一个参数预分配了一个值oo,那么传入参数的时候,最后一个有值的参数可以不用传递;传递参数的时候,如果不指定参数名,那么就默认安装位置传递;如果指定了名字,那么位置可以颠倒。
1
2
3
4
5
6
7
8
|
>>>
def
send(xx,bb,dd
=
"oo"
):
print
(xx,bb,dd)
return
True
send(
23
,
233
,
22
)
send(bb
=
22
,xx
=
33
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
23
233
22
33
22
oo
|
例子(动态参数)
定义了一个*args参数,注意调用的时候,f1(list)和f1(*list)的区别;前者把整个列表当做元组的一个元素,后者把列表转换成元组
1
2
3
4
5
6
7
8
9
10
11
12
|
>>>
def
f1(
*
args):
print
(args,
type
(args))
f1(
11
,
22
,
"ddd"
)
li
=
[
1
,
2
,
3
,
4
]
#把整个列表当做元组的一个元素
f1(li,
'2'
)
#把列表的每一个元素都转换成元组的元素
f1(
*
li)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
(
11
,
22
,
'ddd'
) <
class
'tuple'
>
([
1
,
2
,
3
,
4
],
'2'
) <
class
'tuple'
>
(
1
,
2
,
3
,
4
) <
class
'tuple'
>
|
类似的,定义了一个**args的参数,调用的时候,需要传入字典;同理对应比较f2(dic)和f2(**dic)
1
2
3
4
5
6
7
8
9
10
|
>>>
def
f2(
*
*
args):
print
(args,
type
(args))
f2(n1
=
"alex"
,n2
=
18
)
dic
=
{
'k1'
:
'v1'
,
'k2'
:
'v2'
}
f2(kk
=
dic)
f2(
*
*
dic)
#直接赋值
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{
'n1'
:
'alex'
,
'n2'
:
18
} <
class
'dict'
>
{
'kk'
: {
'k1'
:
'v1'
,
'k2'
:
'v2'
}} <
class
'dict'
>
{
'k1'
:
'v1'
,
'k2'
:
'v2'
} <
class
'dict'
>
|
例子(万能参数)
1
2
3
4
5
6
7
8
9
|
>>>
#形式参数的名字可以变换,但是默认习惯使用以下
def
f1(
*
args,
*
*
kwargs):
print
(args)
print
(kwargs)
#自动把列表顺序的(一个星)放第一个参数,字典格式的放第二个(两星的)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
f1(
11
,
22
,
33
,
44
,k1
=
'v1'
,k2
=
'v2'
)
(
11
,
22
,
33
,
44
)
{
'k1'
:
'v1'
,
'k2'
:
'v2'
}
|
看看万能参数的实际应用,比如字符串有个format的函数,它的解释是这样的
1
2
3
4
5
6
7
8
|
def
format
(
self
,
*
args,
*
*
kwargs):
# known special case of str.format
"""
S.format(*args, **kwargs) -> str
Return a formatted version of S, using substitutions from args and kwargs.
The substitutions are identified by braces ('{' and '}').
"""
pass
|
使用的时候,传递列表的效果
1
2
3
4
5
6
7
|
>>> s1
=
"i am {0},age {1}"
.
format
(
"alex"
,
18
)
#自动封装到*args 里面
print
(s1)
s2
=
"i am {0},age {1}"
.
format
(
*
[
"alex"
,
18
])
#自动封装到*args 里面
print
(s2)
-
-
-
-
-
-
-
-
-
-
-
-
-
i am alex,age
18
i am alex,age
18
|
传递字典的效果
1
2
3
4
5
6
|
>>> s
=
"iam {name},age{age}"
.
format
(name
=
'alex'
,age
=
19
)
#传到了**kwargs
dic
=
{
'name'
:
'alex'
,
'age'
:
189
}
s2
=
"iam {name},age{age}"
.
format
(
*
*
dic)
#传到了**kwargs
print
(s2)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
iam alex,age189
|
几个注意事项注意事项:
1.当定义函数的时候,如果定义了2个重名的函数,因为是按照顺序放入内存的,那么后面的函数会覆盖前面的定义
2.很重要的一点,函数参数传递的是引用,而不是拷贝,因此内容会一起改变
3.在函数后面直接输入""",然后回车会自动生成注释的格式
4.如果使用全局变量,约定俗成的习惯是全部大写,如果要在函数中修改,需要使用global
例子(传递的参数在函数中发生了改变,在函数外也同时发生了改变)
1
2
3
4
5
6
7
8
9
10
11
|
>>>
def
f1(a):
'''
:param a:
:return:
'''
a.append(
999
)
li
=
[
1
,
2
,
3
]
f1(li)
print
(li)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[
1
,
2
,
3
,
999
]
|
例子 全局变量如果需要在函数里面修改,需要使用global关键字
1
2
3
4
5
6
7
8
|
>>> a
=
10
def
f1(num):
global
a
a
+
=
num
print
(a)
f1(
20
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
30
|
三元运算和lambda 表达式
三元运算:有些简单的if..else语句可以直接用一行表示
例子
1
|
name
=
"alex"
if
1
=
=
1
else
"sb"
|
lambda表达式,一些简单的函数也可以用一行表示
例子
下面的函数等同于一行就实现的lambda表达式
1
2
3
4
5
6
|
>>>
def
f1(a1):
return
a1
+
100
ret
=
f1(
10
)
print
(ret)
-
-
-
-
-
-
-
-
-
-
110
|
lambda表达式,对比上面的正式写法,冒号前面的是形式参数;冒号后面是函数的主体,函数的结果自动返回
1
2
3
4
5
|
>>> f2
=
lambda
a1:a1
+
100
#冒号前面是参数,注意只能用一行
r2
=
f2(
9
)
print
(r2)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
109
|
最后看看种类繁多的内置函数
例子:
abs()求绝对值
1
2
3
|
>>>
print
(
abs
(
-
1
))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
1
|
bool()返回布尔值,注意0,None,"",[],{},() 返回的布尔值都是False
1
2
3
4
5
|
>>>
print
(
bool
(
None
))
print
(
bool
(()))
-
-
-
-
-
-
-
-
False
False
|
all()里面传入可以迭代的对象,比如列表,字典,如果每一个对象的布尔值都是真,那么结果为真,其中一个为假,结果为假
any()和all()相对应,如果有一个对象为真,那么他的结果就是真
1
2
3
4
|
>>> n
=
all
([
1
,
2
,
3
,
4
,
None
])
print
(n)
-
-
-
-
-
-
-
-
False
|
1
2
3
4
|
>>> m
=
any
([
1
,
0
,""])
print
(m)
-
-
-
-
-
-
-
-
-
-
True
|
ascii(),自动执行对象的_repr_方法,比如定义了一个class,该class里面有一个_repr_的方法,那么他会自动执行。
bin() 10进制转2进制
oct() 10进制转8进制
hex() 10进制转16进制
1
2
3
4
5
6
7
|
>>>
print
(
bin
(
5
))
print
(
oct
(
9
))
print
(
hex
(
15
))
-
-
-
-
-
-
-
-
-
-
0b101
0o11
0xf
|
byte() 把字符串转换为字节,请注意编码不同,汉字的转换不同
utf-8 1个汉字是3个字节,gbk一个汉字 2个字节
utf-8,一个字节8位,一个汉字3个字节,所以一个汉字24位
如下所示,同样的“李杰”转换成utf-8是6个字节,而gbk只有4个字节
1
2
3
4
5
6
7
8
9
|
>>> s
=
"李杰"
#把字符串转换成字节类型
n
=
bytes(s,encoding
=
"utf-8"
)
print
(n)
n
=
bytes(s,encoding
=
"gbk"
)
print
(n)
-
-
-
-
-
-
-
-
-
-
-
-
-
b
'\xe6\x9d\x8e\xe6\x9d\xb0'
b
'\xc0\xee\xbd\xdc'
|
str()和bytes功能相反,把字节转换为字符串,同样需要指定编码
1
2
3
4
5
|
>>>
#字节转换成字符串
m
=
str
(bytes(s,encoding
=
"utf-8"
),encoding
=
"utf-8"
)
print
(m)
-
-
-
-
-
-
-
-
-
-
李杰
|
callable()判断是否可以是调用的函数
1
2
3
4
5
6
7
8
|
>>>
def
f1():
pass
f1()
f2
=
123
print
(
callable
(f1))
print
(
callable
(f2))
True
False
|
chr()和ord()都是用来进行ASCII码的转换,前者是把代码转换成对应的字符;后者是把字符转换成代码
1
2
3
4
5
6
7
|
>>>
#ASCII 转换
r
=
chr
(
65
)
print
(r)
n
=
ord
(
"B"
)
print
(n)
A
66
|
随机数
比如ASCII 65-90 代表 A-Z,我选择一个范围,随机生成一个数字,然后把这个数字转换成字符就是一个随机的英文字符
1
2
3
4
5
6
|
>>>
import
random
i
=
random.randrange(
65
,
91
)
c
=
chr
(i)
print
(c)
-
-
-
-
-
-
-
-
-
-
H
|
例子 生成一组随机的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import
random
li
=
[]
for
i
in
range
(
6
):
r
=
random.randrange(
0
,
5
)
if
r
=
=
2
or
r
=
=
4
:
num
=
random.randrange(
0
,
10
)
li.append(
str
(num))
else
:
temp
=
random.randrange(
65
,
91
)
c
=
chr
(temp)
li.append(c)
res
=
"".join(li)
print
(li)
print
(res)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[
'T'
,
'Q'
,
'G'
,
'2'
,
'Q'
,
'6'
]
TQG2Q6
|
当执行一个Phython文件的时候,他一般会经过以下几个步骤
-
读取文件内容,把读取的字符串保存到内存
-
python把这些字符串编译为特殊代码
-
执行这些代码
比如saltstack,django的语法,其实最后都是转换成python的字符串,然后通过python编译执行。
下面是相关的一些函数
compile()把字符串转换成python代码
exec()执行任意的的Python代码,没有返回值
eval()执行运算表达式,有返回值
例子
compile可以把字符串转换成代码,然后exec来执行这个代码
1
2
3
4
5
6
7
|
s
=
"print(123)"
r
=
compile
(s,
"<string>"
,
"exec"
)
print
(r)
exec
(r)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<code
object
<module> at
0x000001CB92285D20
,
file
"<string>"
, line
1
>
123
|
当然exec()也可以直接执行,他会自动转换之后再编译执行
1
2
3
|
>>>
exec
(
"print(123)"
)
-
-
-
-
-
123
|
当使用eval()的时候,我们可以有返回值,比如
1
2
3
4
5
6
|
>>>s
=
"6*8"
ret
=
eval
(s)
print
(ret)
exec
(
"print(11)"
)
-
-
-
-
-
-
-
-
-
-
-
-
48
|
dir()可以快速查看他有哪些函数
1
2
3
|
print
(
dir
(
dict
))
-
-
-
-
-
-
-
-
-
-
-
[
'__class__'
,
'__contains__'
,
'__delattr__'
,
'__delitem__'
,
'__dir__'
,
'__doc__'
,
'__eq__'
,
'__format__'
,
'__ge__'
,
'__getattribute__'
,
'__getitem__'
,
'__gt__'
,
'__hash__'
,
'__init__'
,
'__iter__'
,
'__le__'
,
|
如果想查看细节,可以用help()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
help
(
list
)
-
-
-
-
-
-
-
-
-
-
-
Help
on
class
list
in
module builtins:
class
list
(
object
)
|
list
()
-
> new empty
list
|
list
(iterable)
-
> new
list
initialized
from
iterable's items
|
| Methods defined here:
|
| __add__(
self
, value,
/
)
| Return
self
+
value.
|
| __contains__(
self
, key,
/
)
| Return key
in
self
...
|
divmod()用来取商和余数
比如
1
2
3
4
5
6
7
|
>>> r
=
divmod
(
97
,
10
)
print
(r)
n1,n2
=
divmod
(
97
,
10
)
print
(n1,n2)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
(
9
,
7
)
9
7
|
isinstance()判断一个对象是否为某个类的实例
比如字符串alex是str的一个实例,所以返回值为True
1
2
3
4
|
>>> s
=
"alex"
r
=
isinstance
(s,
str
)
print
(r)
True
|
filter(),第一个参数参数传入函数,第二个参数传入一个可以迭代的对象,比如列表;在filter 内部,循环第二个参数,让每个循环元素执行函数(第一个参数),如果返回为True,表示元素合法
例如下面一个函数的效果
1
2
3
4
5
6
7
8
9
10
11
|
def
f1(args):
res
=
[]
for
item
in
args:
if
item >
22
:
res.append(item)
return
res
li
=
[
11
,
22
,
33
,
44
,
55
]
ret
=
f1(li)
print
(ret)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[
33
,
44
,
55
]
|
他可以用filter来实现
1
2
3
4
5
6
7
|
>>>
def
f2(a):
if
a >
22
:
return
True
ret
=
filter
(f2,li)
print
(
list
(ret))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[
33
,
44
,
55
]
|
例:结合lambda表达式,可以很简便
1
2
3
4
5
6
7
8
9
|
>>> f1
=
lambda
a: a>
30
ret
=
f1(
90
)
print
(ret)
li
=
[
11
,
22
,
33
,
44
,
55
]
res
=
filter
(
lambda
a:a >
14
,li)
print
(
list
(res))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
True
[
22
,
33
,
44
,
55
]
|
map()的使用方式和filter类似,第一个参数是函数,第二个参数是可以迭代的对象
比如,下面一个例子
1
2
3
4
5
6
7
8
9
10
|
>>> li
=
[
11
,
22
,
33
,
44
,
55
]
def
f1(args):
res
=
[]
for
i
in
args:
res.append(
100
+
i)
return
res
r
=
f1(li)
print
(
list
(r))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[
111
,
122
,
133
,
144
,
155
]
|
同样的功能如果用map实现的话
1
2
3
4
5
6
|
>>>
def
f2(a):
return
a
+
100
result
=
map
(f2,li)
print
(
list
(result))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
[
111
,
122
,
133
,
144
,
155
]
|
区别:
filter: 函数返回True; 将元素添加到结果中
map:把函数返回值添加到结果中
float()转换到浮点型
set()集合
fronzenset()不可变的集合
globals()所有全局变量
locals()所有局部变量
例
1
2
3
4
5
6
7
8
9
10
11
12
|
>>> NAME
=
"ALEX"
def
show():
a
=
123
c
=
123
print
(
locals
())
print
(
globals
())
show()
-
-
-
-
-
-
-
-
-
-
-
-
{
'c'
:
123
,
'a'
:
123
}
{
'NAME'
:
'ALEX'
,
'show'
: <function show at
0x0000025EFD3DB488
>,
'sys'
: <module
'sys'
(built
-
in
)>,
'__builtins__'
: {
'PendingDeprecationWarning'
: <
class
'PendingDeprecationWarning'
>,
'IndexError'
: <
class
'IndexError'
>,
'SystemError'
: <
class
'SystemError'
>,
'abs'
: <built
-
in
function
abs
>,
'getattr'
: <built
-
in
function
getattr
>,
'iter'
: <built
-
in
function
iter
>,
'BaseException'
: <
class
'BaseException'
>,
'UnicodeDecodeError'
: <
class
'UnicodeDecodeError'
>,
'sum'
: <built
-
in
function
sum
>,
'id'
: <built
-
in
function
id
>,
'setattr'
: <built
-
in
function
setattr
>,
'__doc__'
:
"Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices."
,
'ProcessLookupError'
: <
class
'ProcessLookupError'
>,
'NotImplemented'
: NotImplemented,
'memoryview'
: <
class
'memoryview'
>,
'str'
: <
class
'str'
>,
'RuntimeError'
: <
class
'RuntimeError'
>,
'print'
: <built
-
in
function
print
>,
'enumerate'
: <
class
'enumerate'
>,
'BrokenPipeError'
: <
class
'BrokenPipeError'
>,
'open'
: <built
-
in
function
open
>,
'eval'
: <built
-
in
function
eval
>,
'KeyError'
: <
class
'KeyError'
>,
'locals'
: <built
-
in
function
locals
>,
'UnicodeWarning'
: <
class
'UnicodeWarning'
>,
'__import__'
: <bound method ImportHookManager.do_import of <module
'_pydev_bundle.pydev_import_hook.import_hook'
>>,
'__spec__'
: ModuleSpec(name
=
'builtins'
, loader
=
<
class
'_frozen_importlib.BuiltinImporter'
>),
'ZeroDivisionError'
: <
class
'ZeroDivisionError'
>,
'int'
: <
class
'int'
>,
'license'
:
Type
license() to see the full license text,
'isinstance'
: <built
-
in
function
isinstance
>,
'len'
: <built
-
in
function
len
>,
'LookupError'
: <
class
'LookupError'
>,
'OverflowError'
: <
class
'OverflowError'
>,
'dict'
: <
class
'dict'
>,
'__debug__'
:
True
,
'dir'
: <built
-
in
function
dir
>,
'BlockingIOError'
: <
class
'BlockingIOError'
>,
'range'
: <
class
'range'
>,
'super'
: <
class
'super'
>,
'PermissionError'
: <
class
'PermissionError'
>,
'FutureWarning'
: <
class
'FutureWarning'
>,
'True'
:
True
,
'FileNotFoundError'
: <
class
'FileNotFoundError'
>,
'staticmethod'
: <
class
'staticmethod'
>,
'TabError'
: <
class
'TabError'
>,
'hex'
: <built
-
in
function
hex
>,
'__name__'
:
'builtins'
,
'copyright'
: Copyright (c)
2001
-
2016
Python Software Foundation.
All
Rights Reserved.
Copyright (c)
2000
BeOpen.com.
|
hash() 生成哈希值,然后保存到内存;一般用于比如字典的key转换成哈希值的保存,做索引
1
2
3
4
|
s
=
"hhh"
print
(
hash
(s))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
3961184104134240409
|
len()输出长度,Python3是显示字符,而2显示的是字节
1
2
3
4
5
6
7
|
>>> s
=
"理解"
#python 3 是2(字符),2.7是6(字节)
print
(
len
(s))
b
=
bytes(s,encoding
=
"utf8"
)
print
(
len
(b))
-
-
-
-
-
-
-
-
-
-
-
-
2
6
|
max()最大
min()最小
sum()求和
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>>
r
=
max
([
11
,
22
,
33
])
print
(r)
l
=
min
([
11
,
22
,
33
])
s
=
sum
([
1
,
2
,
3
])
print
(l,s)
>>> r
=
max
([
11
,
22
,
33
])
print
(r)
l
=
min
([
11
,
22
,
33
])
s
=
sum
([
1
,
2
,
3
])
print
(l,s)
33
11
6
|
pow()求指数,效果和两个*一样
1
2
3
4
|
>>>
print
(
2
*
*
10
)
print
(
pow
(
2
,
10
))
1024
1024
|
reverse翻转,下面例子两个表达效果一样
1
2
3
4
|
>>> 翻转
li
=
[
11
,
22
,
33
]
li.reverse()
reversed
(li)
|
zip()可以把多个列表的列抽出来
1
2
3
4
5
6
|
>>> l1
=
[
"alex"
,
11
,
22
,
33
]
l2
=
[
"is"
,
11
,
22
,
33
]
l3
=
[
"sb"
,
11
,
22
,
33
]
r
=
zip
(l1,l2,l3)
print
(
list
(r)[
0
])
(
'alex'
,
'is'
,
'sb'
)
|