首页 > 代码库 > 初学Python(九)——函数

初学Python(九)——函数

初学Python(九)——函数

  

  初学Python,主要整理一些学习到的知识点,这次是函数。

 

函数定义:

# -*- coding:utf-8 -*-  
  
  
#函数的定义  
def my_function(x):  
    if x>0:  
        return x  
    elif x<0:  
        return -x  
    else:  
        pass  
#函数的调用  
a = my_function(-1)  
b = my_function(2)  
c = my_function(0)  
print a,b,c  
  
#空函数,pass为占位符  
def empty_function(x):  
    pass  
  
print empty_function(-1)  
  
#参数检查,给my_function函数加上参数检查  
def my_function(x):  
    if not isinstance(x,(int,float)):  
        #raise相当于java中的throw,抛出异常  
        raise TypeError(UnExpectedType)  
    elif x>=0:  
        return x  
    else:  
        return -x  
  
print my_function(1)  
print my_function(-1)  
#print my_function(‘a‘)  
#返回多个值,牛er逼  
def multi_function(x):  
    x0 = x+1  
    x1 = x-1  
    #返回的其实就是一个tuple  
    return x0,x1  
  
print multi_function(2) 

 

参数:

#-*- coding:utf-8 -*-  
  
‘‘‘‘‘ 
默认参数: 
就是你不指定该参数的值时, 
该参数有一个默认值 
‘‘‘  
def default_para(x,n=2,s=3):  
    return x*n*s  
print default_para(2)  
print default_para(2,3)  
print default_para(2,n=5)  
print default_para(2,s=3)  
print default_para(2,n=2,s=4)  
  
  
#天坑  
def default_para_hole(L=[]):  
    L.append(ITFOOTBALLCLUB)  
    return L  
print default_para_hole()  
print default_para_hole()  
‘‘‘‘‘ 
第一遍为[‘ITFOOTBALLCLUB‘] 
第二遍为[‘ITFOOTBALLCLUB‘, ‘ITFOOTBALLCLUB‘] 
问题在于L的值在定义函数时就已经指明了对象, 
如果你不指定参数,他默认只指向该对象, 
如果该对象变了,那么默认参数的值也会变 
所以要尽量使用不可变对象[]改为None 
‘‘‘  
  
#去天坑版,None为不可变对象  
def default_para_no_hole(L=None):  
    if L is None:  
        L = []  
    L.append(ITFOOTBALLCLUB)  
    return L  
  
print default_para_no_hole()  
print default_para_no_hole()  
  
  
‘‘‘‘‘ 
可变参数: 
意思就是参数的个数是0..n个的 
‘‘‘  
#不用可变参数也能传入多个参数,使用list和tuple  
def changeable_para(multi):  
    sum = 0  
    for n in multi:  
        sum+=n  
  
    return sum  
#0  
print changeable_para([])  
#list  
print changeable_para([1,2,3,4,5])  
#tuple  
print changeable_para((1,2,3,4))  
  
‘‘‘‘‘ 
上面的方式也能实现传入0..n个参数的传递, 
但是需要实现组装为list或tuple 
如果你本来就有一个list或tuple,这么用 
无可厚非 
如果你不想每次都组装,你就可以使用可变参数 
‘‘‘  
  
#改装版,可变参数就是在参数前加上一个星号(*),so easy  
def changeable_para_update(*multi):  
    sum = 0  
    for n in multi:  
        sum+=n  
    return sum  
  
print changeable_para_update(1,2,3)  
  
#如果你本来就有list,可变参数也能融合  
name = [1,3,4,7,9]  
print changeable_para_update(*name)  
  
#这样是不是犀利多了  
  
  
‘‘‘‘‘ 
关键字参数: 
传递0...n个带参数名的参数 
参数名前加2个星号 
‘‘‘  
  
def key_para(x,y,n=2,*numbers,**kp):  
    print x,y,n,numbers,kp  
#只有必选参数      
key_para(1,2)  
#必选,默认  
key_para(1,2,3)  
#必选,默认,关键字  
key_para(1,2,3,kw=99)  
#必选,默认,可变(数组)  
key_para(1,2,3,*[1,2])  
#必选,默认,可变(数组)  
key_para(1,2,3,*(1,2))  
#必选,默认,可变  
key_para(1,2,3,1,2)  
#必选,默认,关键字(字典)  
key_para(1,2,3,**{test:af,pld:afe})  
#必选,默认,可变,关键字  
key_para(1,2,3,*(1,2),kw=99)  
  
  
#所有的函数参数都可以用func(*args,**kw)来调用 

 

递归函数:

# -*- coding:utf-8 -*-  
  
‘‘‘‘‘ 
递归函数 
‘‘‘  
  
def fact(n):  
    if n==1:  
        return 1  
    return fact(n-1)*n  
  
print fact(10)  
  
print fact(100)  
  
  
#尾递归解决栈溢出  
#栈溢出  
#print fact(1000)  
#尾递归  
def fact(n):  
    return fact_iter(1,1,n)  
def fact_iter(n,count,max):  
    if count > max:  
        return n  
    return fact_iter(n*count,count+1,max)  
‘‘‘‘‘ 
但是python没有对尾递归做优化, 
所以上面的尾递归依然会栈溢出, 
(那还说个毛啊),不过国外有 
人写了个装饰器,可以解决这个问题 
有时间研究一下 
‘‘‘  

 

防止溢出:

#!/usr/bin/env python2.4  
# This program shows off a python decorator(  
# which implements tail call optimization. It  
# does this by throwing an exception if it is   
# it‘s own grandparent, and catching such   
# exceptions to recall the stack.  
  
import sys  
  
class TailRecurseException:  
  def __init__(self, args, kwargs):  
    self.args = args  
    self.kwargs = kwargs  
  
def tail_call_optimized(g):  
  """ 
  This function decorates a function with tail call 
  optimization. It does this by throwing an exception 
  if it is it‘s own grandparent, and catching such 
  exceptions to fake the tail call optimization. 
   
  This function fails if the decorated 
  function recurses in a non-tail context. 
  """  
  def func(*args, **kwargs):  
    f = sys._getframe()  
    if f.f_back and f.f_back.f_back \  
        and f.f_back.f_back.f_code == f.f_code:  
      raise TailRecurseException(args, kwargs)  
    else:  
      while 1:  
        try:  
          return g(*args, **kwargs)  
        except TailRecurseException, e:  
          args = e.args  
          kwargs = e.kwargs  
  func.__doc__ = g.__doc__  
  return func  
 
@tail_call_optimized  
def factorial(n, acc=1):  
  "calculate a factorial"  
  if n == 0:  
    return acc  
  return factorial(n-1, n*acc)  
  
print factorial(10000)  
# prints a big, big number,  
# but doesn‘t hit the recursion limit.  
 
@tail_call_optimized  
def fib(i, current = 0, next = 1):  
  if i == 0:  
    return current  
  else:  
    return fib(i - 1, next, current + next)  
  
print fib(10000)  
# also prints a big number,  
# but doesn‘t hit the recursion limit. 

 

初学Python(九)——函数