函数
函数就是完成特定功能的一个语句组,这组语句可以作为一个单位使用,并且给它取一个名
可以通过函数名在程序的不同地方多次执行(通常叫函数调用)
预定义函数:可以直接使用
自定义函数:自己编写
为什么使用函数
降低编程难度
通常将一个复杂的大问题,分解成一系列的小问题,然后将小问题,然后将小问题划分成更小的问题,当问题细化为足够简单时,我们就可以分而治之,各个小问题解决了,大问题就迎刃而解了
代码重用
避免重复劳作,提高效率
函数的定义和调用
def 函数名([参数列表])://定义
函数名([参数列表]) : //定义
#!/usr/bin/python
def fun():
print ("hello world!")
fun()
函数的参数
形式参数和实际参数
在定义函数时,函数名后面括号中的变量名称叫做“形式参数”,或者称为“形参”
在调用函数时,函数名后面括号中的变量名称叫做“实际参数”。或者称为“实参”
#!/usr/bin/python
import sys
# sys.argv #读取脚本后跟的参数
def isNmu(s):
for i in s:
if i in '0123456789':
pass
else:
print "%s is not number" % s
sys.exit()
else:
print ("%s is a number") % s
isNum(sys.argv[1])
注:
for循环也有else,当for循环正常结束的时候才会执行else的内容。
练习
打印系统的所有PID
要求从 /proc 读取os.listdir('/proc')
将该路径下的文件名读取出来返回列表
#!/usr/bin/python
import sys
import os
def isNum(s): #定义一个方法
for i in s: #因为列表有很多值,所有用for
if i in '0123456789': #判断这个字符是不是在里段里面
pass #在,就不动作
else: #否则
break #退出当前循环
# print "%s is a not number" % s
else: #for 的else,当for循环正常结束时,则输出eles里面的内容
print s #打印输出
for i in os.listdir('/proc'):
# 使用方法。调用了一个系统函数,它去循环目录的内容然后返回列表,列表里面的都是字符串
isNum(i) #最后将值传递个上面的方法
函数的默认参数
缺省参数(默认参数) #未定义参数时,默认参数为其值。 只能在所有参数的最后去定义,
def fun(x,y=100):
print x+y
fun(1,2)
3
fun(1)
101
函数变量
1.局部变量和全局变量
2.pyhton中的任何变量都有特定的作用域
3.在函数中定义的变量一般只能在该函数内部使用,这些只能在程序的特定部分使用的变量我们称之为局部变量
4.在一个文件顶部定义的变量可以供文件中的任何函数调用,这些可以作为整个程序所使用的变量称为全局变量
#!/usr/local/python
#-*- coding:utf-8 -*-
a='asd' #这是文件头部定义的是全局变量。
def fun():
x = 100
global y #申明为全局变量,只有调用这个函数时才生效
y = 1
print locals() #将函数内的所有局部变量返回一个字典
print x
fun() #在函数内部定义,调用函数才有用。
print x,y
print a
输出:
{'x':100,'y':1}
100,1
asd
global x #申明内部的局部变量 为全局变量。只能做申明使用
locals() #在函数内定义的所有变量,返回一个字典,函数外使用即返回全局变量的字典
函数返回值
- 函数被调用后会返回一个指定的值
- 函数调用后默认返回None
- return返回值
- 返回值可以是任何类型
- return执行后,函数终止
- return 与 print 区别
def fun(): #定义函数
print "hello world!" #打印字符串
print fun() #打印输出这个函数
hello world #这是print的输出
None #这是函数的返回值
return
def fun(): #定义函数
print "hello world!" #打印字符串
return True #执行到return就结束了
print "not fun" #这里的print就没输出了
print fun() #打印输出这个函数
hello world #这是print的输出
True #这是函数的返回值
return 的值虽然不是很直观能看到,但是真是存在的!
例子
#!/usr/bin/python
import os
def isNum(s): #定义函数
if s.isdigit(): #判断这个形参是否为数字
return True #如果它是数字,返回一个True
return False #如果它不是数字,返回一个False
for i in os.listdir('/proc'): #用一个方法去读取该目录下的所有文件名
if isNum(i): #调用这个函数,传递一个变量给函数,会有返回值
print i #如果上面的函数返回了一个true,则打印这个值,否则不打印
isdigit() 判断字符串内是否是数字,返回bool值。
多类型传值和冗余参数 以及函数的递归调用
多类型传值
- 元组 : 以 * 方式
- 字典 : 以 ** 方式
冗余(rongyu)参数
def fun(x,y):
return x+y
print fun(3,5)
8
t = (1,2) #定义元组
fun(*t) #传入的元组,必须前面加个*,才可以正常输出
3
def fun(x,y,z):
return x+y+z
t = (1,2) #定义元组
fun(2,*t) #还必须放在命名参数的后面 `2+1+2=5`
5
fun(x=1,y=1,z=2) # `1+1+2`=4
4
dict1 = {'x':1,'y':3,'z':2} #字典
fun(**dict1) #传入字典,前面加** 才可以正常输出
6
冗余参数
def fun(x, y, *args, **kwargs)
x,y
:命名参数
*args , **kwargs
:冗余参数
*args
:多余的参数存到这里(可以是字符串,列表),并以元组的方式存入
**kwargs: x=1,y=2,**dit1
这样的存入里面为字典
def fun(x,*args,**kwargs):
print x
print args
print kwargs
fun(1)
1
()
{}
t = (22,'a')
a = ['ada', '32', 'sa2']
type(a)
list
type(t)
tuple
fun(1,'asd','213as',a,*t) #这里的a是列表不用加*,只有是元组的t才加*
1
('asd', '213as', ['ada', '32', 'sa2'], 22, 'a')
{}
dd = {'xx':3,'z':1}
fun1(1,a,*t,**dd) #这里加入了字典,需要前面加入**来表示传入的是字典
1
(['ada', '32', 'sa2'], 22, 'a') #这是*args的内容,包括了字符串,列表,元组
{'xx': 3, 'z': 1} #在最后输出字典
递归调用函数
递归调用:自己调用自己
递归的注意事项
-
必须有最后的默认结果
if n == 0
-
递归参数必须向默认结果收敛的:
factorial(n-1)
#factorial 阶乘的
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
先从循环定义阶乘
#!/usr/bin/python
def factorial(n):
sum = 1 #先定义起始值
for i in range(1,n+1): #for 循环加n
sum *= i #再相乘
return sum #返回这个值
factorial(5) #输入一个值
输出: 120
#!/usr/bin/python
def factorial(n):
sum = 0
for i in range(1,n+1):
sum += i
return sum
factorial(100)
输出: 5050
递归函数 : * 法
#!/usr/bin/python
def factorial(n):
if n == 0:
return 1 #因为是乘法,如果返回0则任何结果*0返回都是0,如果*1则返回它本身
else:
return n * factorail(n-1) #n-1在收敛
factorial(5)
120 # 递归的结果是这样的:5*4*3*2*1
factorial(10)
3628800 # 10*9*8*....*1
-------------------------------------------------------------------------------
执行过程
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1)))) #n-1在收敛,先把n-1符合了if的return 1。再由内向外运算
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120 # if n == 0 ; return 1 -> 120*1=120
-------------------------------------------------------------------------------
递归函数 : + 法
def factorial(n):
if n == 0:
return 0 #因为是+法,所以最后返回的是0,任何数+0都等于它本身
else:
return n + factorail(n-1) #n-1在收敛
print factorial()
factorial(100)
5050
factorial(3)
3 + 2 + 1 +0
6
---------------------------------------------------------
3 -> n: 3
3 + (3-1) -> n: 2
3 + (3-1) + ((3-1)-1) -> n: 1
3 + (3-1) + ((3-1)-1) + (((3-1)-1)-1) -> n: 0
---------------------------------------------------------
factorial(5)
5 + 4 + 3 + 2 + 1 +0
15
程序: 乘法和加法递归
#!/usr/bin/python
import sys
def factorial1(n):
if n == 0:
return 1
else:
return n * factorial1(n-1)
def factorial2(n):
if n == 0:
return 0
else:
return n + factorial2(n-1)
print "n * (n-1) = " + str(factorial1(int(sys.argv[1])))
print "n + (n-1) = " + str(factorial2(int(sys.argv[1])))
输出:
[root@hc python]# python factorial.py 1
n * (n-1) = 1
n + (n-1) = 1
[root@hc python]# python factorial.py 2
n * (n-1) = 2
n + (n-1) = 3
[root@hc python]# python factorial.py 3
n * (n-1) = 6
n + (n-1) = 6
[root@hc python]# python factorial.py 4
n * (n-1) = 24
n + (n-1) = 10
[root@hc python]# python factorial.py 5
n * (n-1) = 120
n + (n-1) = 15
[root@hc python]# python factorial.py 6
n * (n-1) = 720
n + (n-1) = 21
[root@hc python]# python factorial.py 7
n * (n-1) = 5040
n + (n-1) = 28
[root@hc python]# python factorial.py 8
n * (n-1) = 40320
n + (n-1) = 36
[root@hc python]# python factorial.py 9
n * (n-1) = 362880
n + (n-1) = 45
[root@hc python]# python factorial.py 10
n * (n-1) = 3628800
n + (n-1) = 55
递归文件和匿名函数
import os
os.listdir('/dir')
输出返回一个列表
使用到了两个内置函数,先加载了import os 这个模块os.path.isdir()
#判断后面的参数是不是一个目录,返回bool
os.path.isfile()
#判断后面的参数是不是一个文件,返回bool
os.path.join('/etc/','passwd')
#连接两个路径
'/etc/passwd/' #join 连接,不管存不存在都连接
打印目录下所有文件
#!/usr/bin/python
import os #调用系统文件
import sys
def print_dir(path): #定义函数
lsdir = os.listdir(path) #先将找到路径的下的所有文件存入列表
dirs = [ i for i in lsdir if os.path.isdir(os.path.join(path, i)) ] #用列表方法将for循环的内容进行判断是不是一个目录
files = [ i for i in lsdir if os.path.isfile(os.path.join(path, i))] #用列表方法将for循环的内容进行判断是不是一个文件
if dirs: #判断这个值是否为空。
for d in dirs: #不为空则 for 循环去遍历里面的内容传给 d 变量
print_dir(os.path.join(path, d)) #递归函数,将形参路径 +上 d 变量的值,组成新的下级路径继续使用函数判断,形成递归
if files:
for f in files: #不为空则 for 循环去遍历里面的内容传给 f 变量
print os.path.join(path, f) #将形参路径 +上 f 变量的值,打印出来文件名
print_dir(sys.argv[1]) #调用内置函数,将命令行后输入的实参传入函数
注:
dirs是过滤出目录的变量,files是过滤出文件的变量,然后再用过滤出的目录放入函数里函数里递归,继续过滤。直到没有目录为止
匿名函数
lambda
lambda 函数是一种快速定义单行的最小函数,可以用在任何需要函数的地方
匿名函数优点
-
使用Python写一些脚本时,使用lambda可以省去定义函数的过程,让代码更加精简
-
对于一些抽象的,不会被别的地方再重复使用的函数,有时候函数起个名字也是个难题,使用lambda不需要考虑命名的问题
-
使用lambda再某些时候让代码更容易理解
def fun(x,y): #定义一个正常函数
return x*y #return 返回运算结果
fun(2,2) #调用函数,输入实参
4 #输出结果
r = lambda a,b:a*b #定义一个匿名函数,返回一个函数对象给一个变量接收
r(2,2) #调用,给这个匿名函数输入实参
4 #返回结果
lambda 基础
- lambda语句中,冒号前是参数,可以有个,逗号隔开,冒号右边是返回值
- lambda语句构建的其实是一个函数对象
内置函数
内置函数 reduce
help(reduce)
reduce(...)
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
将两个参数的函数累加到一个序列的项上,从左到右,以便将序列缩减为单个值。
例如,reduce(lambda x, y: x+y,[1,2,3,4,5])
计算((((1 + 2)+(3)+ 4)+ 5)。
如果有initial,则将它放在项目前面的顺序,并作为默认时序列是空的。
注:
reduce 需要两个参数
一个是函数对象,必须是二元计算(只有两个值的运算).
一个是序列,可以用ranger(1,5)来表示一个序列
def fun(x,y): | ---> | r = lambda x,y:x*y
return x*y | |
fun(2,2) | ---> | r(2,2)
4 | | 4
---------------------------------------------------------------------------------
def add(a,b):
return a+b
reduce(fun,range(1,6)) #调用函数对象!记住 调用的函数对象不是函数
120
reduce(add,range(1,101)) #函数是带()的,函数对象是不带括号的
5050
reduce(lambda x,y:x+y ,range(1,101)) # (lambda x,y:x+y)这一段就是一个函数对象
5050
内置函数
abs()
返回数字的绝对值
取列表最大最小值max()
min()
常用函数len()
统计序列长度
divmod()
返回的是商和它的模,返回的是一个元组,
pow()
两个值的时候是开方,三个数的时候是(xy)%z 开方后取余
pow(2,3) `` ( 2**3 )
2的3次方
8pow(2,3,4) `` (2**3)%4
先开方再取余 8%4 整除,余数为0
0
round()
保留几位浮点数。有两个元素,第一个值是一个浮点数,第二个值是保留小数点后几位的个数,包含四舍五入原则,默认保留小数点后一位
round(12.122,2)
12.12
callable()
判断一个对象是否可被调用的(函数或者类),返回一个bool,可调用返回true,不可调用返回false
type()
返回对象是什么类型的
isinstance()
判断对象是什么类型,第一个参数是对象,第二个参数可以是int or str or list or tuple or dict or class .返回一个bool
a = [1,2,3] ---> list
isinstance(a,list)
True
isinstance(a,str)
False
isinstance(a,(str,list))
只要前面这个对象,属于后面元组里的某一个类型,则返回true
True
cmp()
比较两个对象,返回一个int
cmp(1,1)
0
cmp(1,3) #x>y,1比3小 所以返回-1
-1
cmp(4,3) #x>y ,4比3大 返回 1
1
range()
返回一个列表,直接输出
range(5)
[0,1,2,3,4]
xrange()
和range一样,但是他类似于对象,当做遍历的时候才会占用内存,效率比range 高
类型转换函数
int()
转换一个字符串或者是一个number,返回一个int 整型
long()
转换成长整型 整数后面+L 就会变成long
float()
转换成浮点型
complex()
转换成 复数
str()
转换成字符串,返回一个字符串对象
list()
返回一个列表,可迭代的
tuple()
返回一个元组,可迭代的对象
hex()
一个number转换成16进制字符串,返回一个字符串
eval()
eval(hex(10))
把字符串当做有效的表达式来求值。
eval('0xa')
10
eval("['a','v','b']") #将字符串,返回列表
['a','v','b']
eval("{'a':1,'b':2}") #将字符串,返回字典
{'a':1,'b':2}
chr()
返回对应的ASCII码
chr(100)
'd'
chr(65)
'a'
[chr(i) for i in range(97,123)]
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
ord()
和chr() 相反,参数是ASCII码的值,返回一个整数
ord('a')
97
ord('A')
65
字符串处理函数
str.capitalize()
字符串方法,返回一个字符串,首字母大写
s = 'abc'
s.capitalize()
abc
str.replace()
字符串方法,第一个参数是字符串,后面的是替换字符串,(old,new)旧替换新
help(s.replace)
s = 'hello,h'
s.replace('h','H') #小h 换成了 大H
Hello,H
str.split()
切割字符串,返回一个列表,默认为空格或者TAB键切分,可以指定分隔符。可以指定切多少
s = 'hello, h'
s.split()
['hello',',''h']
s.split(',')
['hello','h']
str.join()
连接字符串,参数是可迭代的对象,返回一个字符串
r
[0, 1, 2, 3, 4]
''.join([str(i) for i in r]) #前面定义为空,则输出'01234'
'01234'
' '.join([str(i) for i in r]) #前面定义为空格,则输出每个字符中间都会有一个空格
'0 1 2 3 4'
' x '.join([str(i) for i in r]) #前面定义为字符x ,则输出每个字符中间都会有一个字符x
'0 x 1 x 2 x 3 x 4'
'.'.join([str(i) for i in r]) #前面定义为字符. 则输出每个字符中间都会有一个字符.
'0.1.2.3.4'
string 模块
import string
先加载模块,才能使用
string.lowercase
打印所有小写字母
import string
string.lowercase
'abcdefghijklmnopqrstuvwxyz'
string.uppercase
打印所有大写的字母
import string
string.uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
序列处理函数
len()
求序列长度,总数
max()
求序列内的最大值
min()
求序列内的最小值
filter()
两个参数,第一个参数是函数或者是None,第二个是序列,返回的可以是list or tuple or string
s='saf@!#asd'
filter(None,'@#!@$%^&%') #过滤用的,
'safasd'
filter(None,range(5))
[1,2,3,4]
def fun(x):
if x % 2 == 0: #当为偶数时
return True #返回turn
filter(fun,range(10))
[0,2,4,6,8]
zip()
一个或者多个序列,返回一个大的列表,里面又有包含元组,对多个序列做处理
a = [1,2,3]
b = ['a','b','c']
-------------------------------
1,2,3
| | | #一一对应
a,b,c
-------------------------------
zip(a,b) #返回大的列表+小的元组
[(1,'a'),(2,'b'),(3,'c')]
dict(zip(a,b)) #返回字典
{'a':1,'b':2,'c':3}
map()
和zip差不多,第一个参数是一个函数
map(None,a,b)
None 去填充其他元素缺少的参数
aa=[1,2,3]
def f(x):
return x**2
map(f,aa) #1**2 , 2**2, 3**2
[1,4,9]
aa=[1,2,3]
bb=[4,5,6]
def f(x,y): #先定义一个函数两个整数相乘
return x * y
map(f, aa, bb)
[4,10,18]
#两个序列相互对应起来,再传给前面的函数再相乘 1*4=4,2*5=10,3*6=18,返回一个列表
------------------------------------------------------
aa=[1,2,3]
bb=[4,5,6]
| | |
x x x --> 相当于这样
* * *
y y y
reduce()
将两个参数的函数累加到一个序列的项上,从左到右,以便将序列缩减为单个值。
`reduce(lambda x,y:x*y , range(1,6))`
120
#range()返回1-5,然后前面匿名函数定义了相乘,所以就是 1*2*3*4*5=120
reduce(lambda x: x%2 == 0, range(10)) #找偶数
[0,2,4,6,8]
map(lambda x,y:x*y , range(1,10), range(1,10))
--------------------------------------------------------------------------
x * y --> 相当于这样,都是一一对应的
--------------------------------------------------------------------------
[1, 4, 9, 16, 25, 36, 49, 64, 81]
列表表达式
列表重写
[ i*2+10 for i in range(10) ]
[10, 12, 14, 16, 18, 20, 22, 24, 26, 28]
[i for i in range(10) if i%3 == 0]
[0, 3, 6, 9]
模块的使用
import os
import sys
import string
#加载系统内置的模块
- 模块是Python 组织代码的基本方式
- 一个Python脚本可以单独运行,也可以导入到另一个脚本中运行,当脚本被导入运行时,我们将其称为模块(module)
- 所以的.py 文件都可以作为一个模块导入
- 模块名与脚本的文件名相同
- 列如我们编写了一个名为hello.py 的脚本,则可以在另一个脚本中调用import hello语句来导入它。
包
Python的模块可以按目录组织为包
创建一个包的步骤:
- 创建一个名字为包名的目录
- 在该目录下创建一个init.py文件
- 根据需要,在该目录下存放脚本文件或已编译的扩展及子包
- import pack.m1, pack.m2, pack.m3
python path
sys.path('dir') #括号内的为目录
vim /root/.bashrc
export PYTHONPATH='dir' #定义linux环境变量,申明为全局变量
vim wc.py
#!/usr/bin/python
def wordCount(s):
chars = len(s) #用len()函数统计字数
words = len(s.split()) #切割单词,用split()切割空的字符串,再len()统计单词
lines = s.count('
') #用count()函数,统计同个元素,重复的次数。
print lines, words, chars
if __name__ == '__main__': #当执行当前文件的时候,则会执行以下操作,
s = open('/etc/passwd').read() #open打开文件,读取每个字符
wordCount(s) #调用函数
内置变量 : __name__
如果 __name__
等于 __main__
则为使用当前程序执行。
如果 __name__
不等于 __main__
则当前程序为模块给别的程序使用
vim import.py
#!/usr/bin/python
import wc #加载模块
s = """assaf
asfsaf
213"""
wc.wordCount(s) #调用模块,必须加上文件名在前面(wc.)
输出如下:
[root@hc python]# python wc.py
19 27 846
[root@hc python]# python import.py
2 3 29
创建包
touch __init__.py
创建这个文件即为创建包,里面可以是空,也可以是对包的描述
In : from python import wc
这里的'python'是该文件的所在的目录,from 'dir' import 模块名
`In : wc.wordCount('123') `
0 1 3
#调用使用
In : wc.wordCount('asfa')
0 1 4
In : from python.wc import wordCount
# 另一种加载,'python.wc':目录.文件名 ,'wordCount':函数名
In : wordCount('dsadsa')
0 1 6
In : from python.wc import wordCount as wc
#加了别名,'python.wc':目录.文件名,'wordCount':函数名,'wc':是函数的别名
In : wc('sdad')
0 1 4
总结
- 模块是一个可以导入的Python脚本文件
- 包是一些按目录组织的模块和子包,目录下有init.py文件,此文件可以存放包的信息
- 导入模块和包的语法:
1. import, import as
2. from ... import ...