函數---參數

# -*- coding:utf-8 -*-
# ------函數(參數)-------------
'''函數是組織好的,可以重複使用的,用來實現單一,或相關聯功能的代碼
定義函數用def語句,一次寫出函數名,括號,括號中的參數和冒號,然後在縮進塊中編寫函數體,
函數的返回用return返回
函數總有返回值,就算沒有return也會返回none
支持遞歸調用,但不能進行尾遞歸優化
一個完整的函數對象由函數和代碼兩部分組成。其中,PyCodeObject 包含了字節碼等執⾏行數據,
⽽而 PyFunctionObject 則爲其提供了狀態信息。
'''
#abs調用
print(123); #123,傳的參數類型和數量必須正確,否則報錯

#比較函數cmp(x,y) x<y return-1,x>y return 1,x=y return 1;
print cmp(4,5); #-1
print cmp(5,4); #1
print cmp(5,5); #0

#數據類型轉換,如int()函數可以將其他數據類型轉換爲整數
a='12';
print type(a); #<type 'str'>
print int(a);  #12
print type(int(a)); #<type 'int'>
print float(a); #12.0
print type(float(a)); #<type 'float'>
print bool(0); #False

#函數名就是指向一個函數對象的引用,可以把函數名賦值給一個變量,相當於給函數起別名
s = cmp #給cmp函數起別名s,s指向cmp函數
print s(5,4);  #1 通過別名調用函數

#-------------------------------------
def sayHello():    #定義函數sayhello
    print 'Hello world!'  #函數塊
sayHello();   #Hello world!  調用


#-----函數參數--------
def output(x):
    print (x);
    if x >0:
        return x;
    else:
        return -x;
output(-9);  #-9
output('a'); #a

#--參數檢查--參數個數不對,python解釋器會報錯,但是類型不對不會報錯(對於自定義函數)
#內置函數abs()如果傳入字符串類型會檢查出來,而我們上例中定義的output()則無法檢查
# def outputs(x):
#     print (x);
#     if not isinstance(x,(int,float)):
#         raise TypeError('you have input a bad object');
#     if x >0:
#         return x;
#     else:
#         return -x;
# outputs('b');
# 這裏會應影響下面代碼的執行,所以我把這一塊全部注掉

'''
File "D:/pycharmhome/venv/demo5.12.27.py", line 51, in <module>
  File "D:/pycharmhome/venv/demo5.12.27.py", line 46, in outputs
  raise TypeError('you have input a bad object');
TypeError: you have input a bad object
'''
#------
def printMax(a,b):
    if a>b:
        print a,'is the bigger one';
    else:
        print b,'is bigger one';
printMax(3,4); #4 is bigger one
x=1;
y=2;
printMax(x,y); #2 is bigger one
printMax('c','b') #c is the bigger one 可以用參數檢查只數int類型

#------空函數---------
#pass 佔位符,用來標記空代碼塊。還沒有想好怎麼寫函數,可以先放一個pass不會報錯
def text():
    pass;
for i in xrange(1,10):
    pass;

#------函數返回多個值--
import math
def move(x,y,step,angle=0):
    nx = x + step * math.cos(angle);
    ny = y - step * math.sin(angle);
    return nx,ny;
x,y = move(100,100,23,30);
print x,y;   #103.547783347 122.724727354
'''
這是一個假象,函數返回的仍是一個值,返回值是一個tuple,在語法上tuple可以省略括號,而
多個變量可以同時接收一個tuple,按位置賦給對應的值,所以,python的函數返回多值其實就是
返回一個tuple,但寫起來方便
'''



#-----------------------------------------------------------------------
#函數的參數 function parameters---
#上面例子中59行printmax函數就進行了傳參
def power(i):
    return i*i;
print power(5) #25
#-------
def power(i,n):
    s = 1;
    while n>0:
        n = n-1; #n控制循環次數,1*i*i*i..控制這裏i出現幾次
        s = s*i;
    return s
print power(5,2); #25 這是power(5)會報錯

#----設置默認參數
def power(i,n=2):
    s = 1;
    while n > 0:
        n = n-1;
        s=s*i;
    return s;
print power(5); #25
print power(2,3); #8 當n>2時明確傳入n

#-定義時,必選參數在前默認參數在後。否則報錯
#函數傳參方式靈活多變,可按照位置順序傳,也可以不關心位置命名來傳
def test(a,b):
    print a,b;
test(1,'a'); #1 a
test(b = 'a', a=1); #1 a

#-默認參數的好處,簡化書寫,不用在調用的時候再輸入值
def stu(name,gender,age = 3,city = '西安'):
    print 'name:',name;
    print 'gender:',gender;
    print 'age:',age;
    print 'city:',city;
stu('二大爺','man');
'''
name: 二大爺
gender: man
age: 3
city: 西安
'''
'''
注意:默認值參數必須指向不變的對象,否則在每次調用的時候他都會記住上次調用的值,當新
調用時會將之前的值和現在傳入的值同時輸出。下面看一個錯誤的例子
'''
def box(i,intlist = []):
    intlist.append(i);
    return intlist;
print box(4); #[4]
print box(3); #[4, 3]
print box(5,[]);#[5] 顯示的提供實參不適用默認值是正確的
print box(5); #[4, 3, 5]再次使用默認值
print box(5); #[4, 3, 5, 5]再再次使用默認值
'''
因爲這裏我用的是list作爲默認值,而list的長度可變,當每次調用的時候都會給裏面添加一個
數字i=?,則在下一次調用的時候list這個表裏都會有上次所添加的數字,來作爲這個box函數中
的默認參數。即第2次 intlist=[4],第3次 intlist=[4,3]...
而如果顯示的給出實參不提供默認值,相當於格式化這個表 即5=intlist,輸出的永遠只有一個數字
'''
#所以通常不用可變對象來作爲默認值
#可以用不變的None來修改上面的例子
def boxs(i,intlist = None):
    if intlist is None:
        intlist = [];
    intlist.append(i);
    return intlist;
print boxs(3); #[3]
print boxs(4); #[4]
#-------------------------------------------------------
#--可變參數--
def num(numbers):
    sum = 0;
    for n in numbers:
        sum = sum + n*n   #
    return sum;
print num([1,2,3]);#14 將參數組裝成一個list sum=1*1+2*2+3*3
print num((2,3)); #13 將參數組裝成一個tuple sum=2*2+3*3

#------用可變參數簡化調用----------------------------------------
def nums(*numbers):
    sum = 0;
    for n in numbers:
        sum = sum + n*n
    return sum;
print nums(2,4); #20
print nums(); #0 可以傳0個參數
#--已經有一個tuple或list,調用可變參數
num = [2,2];
print nums(num[0],num[1]);#8 這樣比較麻煩
print nums(*num); #8 允許在list或者tuple前加*,把list或者tuple的元素變爲可變參數傳進去

#-----------------------------------------------------
#--關鍵字參數---
# 可變參數允許傳入0或人一個參數,這些可變參數在函數調用是自動組裝爲一個tuple。而關鍵字
# 參數允許傳入0個或任意個含參數名的參數,這些關鍵字參數在函數內部自動組裝爲一個dict

def person(name,age,**kwargs):
    print 'name:',name,'age:',age,kwargs;
print person('二大爺','77',qq = 123,email = '[email protected]');
# name: 二大爺 age: 77 {'qq': 123, 'email': '[email protected]'}
#也可以先組裝一個dict,然後,把dict轉換爲關鍵字傳進去

kw = {'city':'xianyang',
          'job':'teacher',
          'qq':123}
print person('二大爺',77,city = kw['city'],job=kw['job']);
# name: 二大爺 age: 77 {'city': 'xianyang', 'job': 'teacher'}

print person('二大爺',77,**kw);
# name: 二大爺 age: 77 {'qq': 123, 'city': 'xianyang', 'job': 'teacher'}

# -------參數組合--------------
def allbox(a,b,c=0,*args,**kwargs):
    print 'a:',a,'b:',b; #必選參數
    print 'c:',c; #默認參數
    print 'args:',args; #可變參數
    print 'kwargs:',kwargs #關鍵字參數
print allbox(1,2);
'''
a: 1 b: 2
c: 0
args: ()
kwargs: {}
None
'''
print allbox(1,2,3,'a','b','c',d = 4,e = 5);
'''
a: 1 b: 2
c: 3
args: ('a', 'b', 'c')
kwargs: {'e': 5, 'd': 4}
'''
#也可以通過tuple和dict調用
args = (1,2,3,4,5); #list也行
kwargs = {'e':4};
print allbox(*args,**kwargs);
'''
a: 1 b: 2
c: 3
args: (4, 5)
kwargs: {'e': 4}
'''

# -------補充-----------
# 變參智能功能放在所有定義參數的尾部,切**kwargs必須是最後一個。
def tes(*arg,**kwargs):    #可接收任意參數的函數
    print arg;
    print kwargs;
print tes(1,2,'a','b',c='c',d='d'); #位置(必選)、命名(關鍵字)
'''
(1, 2, 'a', 'b')
{'c': 'c', 'd': 'd'}
'''
print tes('a'); #只傳位置參數
'''
('a',)
{}
'''
print tes(a='a');#只傳命名(關鍵字)參數
'''
()
{'a': 'a'}
'''

#-----------可以展開序列類型和字典,將全部元素當多個實參使用。不展開僅是單個實參對象
def zk(a,b,*args,**kwargs):
    print a,b;
    print args;
    print kwargs;
print zk(*xrange(1,7));
'''
1 2
(3, 4, 5, 6)
{}
'''
#單個*用來展開序列類型,或者僅是字典的主鍵列表。**用來展開字典的值,如果沒有變參收集
# 展開後多餘的參數會引發異常.如上例把*args去掉就有異常;
def zk_dic(a,b):
    print a;
    print b;
dic = {'a':4,'b':5};
print zk_dic(*dic);
'''
a
b
'''
print zk_dic(**dic);
'''
4
5
'''


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章