Python 函数

函数

函数就是完成特定功能的一个语句组,这组语句可以作为一个单位使用,并且给它取一个名

可以通过函数名在程序的不同地方多次执行(通常叫函数调用)

预定义函数:可以直接使用

自定义函数:自己编写

为什么使用函数
降低编程难度
通常将一个复杂的大问题,分解成一系列的小问题,然后将小问题,然后将小问题划分成更小的问题,当问题细化为足够简单时,我们就可以分而治之,各个小问题解决了,大问题就迎刃而解了

代码重用
避免重复劳作,提高效率

函数的定义和调用
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() #在函数内定义的所有变量,返回一个字典,函数外使用即返回全局变量的字典

函数返回值

  1. 函数被调用后会返回一个指定的值
  2. 函数调用后默认返回None
  3. return返回值
  4. 返回值可以是任何类型
  5. return执行后,函数终止
  6. return 与 print 区别

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值。



多类型传值和冗余参数 以及函数的递归调用

多类型传值

  1. 元组 : 以 * 方式
  2. 字典 : 以 ** 方式

冗余(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}           #在最后输出字典

递归调用函数

递归调用:自己调用自己

递归的注意事项

  1. 必须有最后的默认结果
    if n == 0

  2. 递归参数必须向默认结果收敛的:
    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 函数是一种快速定义单行的最小函数,可以用在任何需要函数的地方

匿名函数优点

  1. 使用Python写一些脚本时,使用lambda可以省去定义函数的过程,让代码更加精简

  2. 对于一些抽象的,不会被别的地方再重复使用的函数,有时候函数起个名字也是个难题,使用lambda不需要考虑命名的问题

  3. 使用lambda再某些时候让代码更容易理解

def fun(x,y):     #定义一个正常函数
    return x*y    #return 返回运算结果
 
fun(2,2)        #调用函数,输入实参
4              #输出结果

r = lambda a,b:a*b   #定义一个匿名函数,返回一个函数对象给一个变量接收

r(2,2)        #调用,给这个匿名函数输入实参
4              #返回结果

lambda 基础

  1. lambda语句中,冒号前是参数,可以有个,逗号隔开,冒号右边是返回值
  2. 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次方
8
pow(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
#加载系统内置的模块
  1. 模块是Python 组织代码的基本方式
  2. 一个Python脚本可以单独运行,也可以导入到另一个脚本中运行,当脚本被导入运行时,我们将其称为模块(module)
  3. 所以的.py 文件都可以作为一个模块导入
  4. 模块名与脚本的文件名相同
  5. 列如我们编写了一个名为hello.py 的脚本,则可以在另一个脚本中调用import hello语句来导入它。

Python的模块可以按目录组织为包
创建一个包的步骤:

  1. 创建一个名字为包名的目录
  2. 在该目录下创建一个init.py文件
  3. 根据需要,在该目录下存放脚本文件或已编译的扩展及子包
  4. 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

总结

  1. 模块是一个可以导入的Python脚本文件
  2. 包是一些按目录组织的模块和子包,目录下有init.py文件,此文件可以存放包的信息
  3. 导入模块和包的语法:
   1. import,  import as
   2. from ... import ...



原文地址:https://www.cnblogs.com/huidou/p/10761023.html