https://py.checkio.org/mission/min-max/
主要解決幾件事情
- 比大小,比max傳入max function;比min傳入min function
- 傳入的值不一定為數字型態(int or float),有可能是string or list等型態,因此可能需要判斷傳入值的種類
- (非必要的變數)除此之外,使用者還可以傳入特定的算法或改變型態,例如傳入的float型態,要求轉成int之後再做比較
所以這題一開始就有兩個function
但傳入的值因為不固定有幾個,可能好幾個int,或者只傳入一個list或tuple的int
因此在function上傳值的方式寫成
#def min(*args, **kwargs):
先用懂這兩個傳值意義才能開始解題吧
在這兩個傳值的解釋中,我參考了以下幾個網站:
http://kodango.com/variable-arguments-in-python
http://stackoverflow.com/questions/3394835/args-and-kwargs
http://agiliq.com/blog/2012/06/understanding-args-and-kwargs/
我對這樣的傳入值的基本理解是:
- '*'代表的意思:*是代表解壓縮(unpack)list/tuple,在第三個網站有一個非常棒的解釋,當傳入的值為list/tuple時,他會unpack list/tuple到對應的接收變數上。
def fun(a,b,c):
print (a,b,c)
fun(1,2,3) #output = 1,2,3
l=[1,2,3]
fun(*l) #output = 1,2,3
- *args 是當不知道傳入值的型態以及多少時使用,傳入會變成tuple型態,所以假設只傳入一個list就存在args[0]的位置;假設function的型態為下,可以知道args會把剩下的值接收並包進來做成tuple;如果只傳入一個變數,前面的變數a接收對應變數後,args就只會回傳一個空tuple:
def fun1 (a, *args):
print ("a is "+ str(a))
print ("args is "+ str(args))
fun1(1,2,3,4)
#output:
#a is 1
#args is (2, 3, 4)
fun1(1)
#output:
#a is 1
#args is ()
- '**'代表的意思:**是解壓縮(unpack) dictionary,當傳入dictionary時,會把字典對應的變數傳入,**的字典名稱必須在function的變數中有這個名字,否則會出錯
def fun2(a,b,c):
print (a,b,c)
d={'c':3}
e={'k':4}
fun2(1,2,**d)
#output = 1,2,3
fun2(1,2,**e)
#output: TypeError: fun2() got an unexpected keyword argument 'k'
#因為fun2沒有k這個變數,所以出錯
- **kwargs是接收並轉換成dictionary的型態。
如果要印出字典對應的值,可以使用kwargs['dic'],會印出對應的key;而且接收只能像範例一樣,如果要傳入字典的話也要加**才不會出錯。
def fun3(a, **kwargs):
print (a)
print (kwargs)
print (kwargs['b'])
#假設字典裡沒有傳入b的變數,則會出錯
key = kwargs.get("b", None)
#如果dictionary裡有'b',則key=b對應的值;如果沒有則key=None
fun3(1, b=2, c=3)
#output:
#1
#{'b': 2, 'c': 3}
#2
#2
fun3(1, {'b':2, 'c':3})
#error
fun3(1, **{'b':2, 'c':3})
#output:
#1
#{'b': 2, 'c': 3}
#2
#2
- *args和**kwargs合用在function時,*args一定要擺前面而**kwargs要擺後面
以上知道傳入的變數如何操作以後
就可以繼續解決這題目了
第一個判斷:是否有key值,有key必須用key判斷
因此要使用get的方式抓取
key = kwargs.get("key", None)
有key走key的判斷,None走一般的比大小
第二個判斷:是傳入一個像list類型的複合值,或者是多值
因此先確定args傳入的長度
len(args)
假設長度為一,則傳入的應該是像list /tuple/string等值
作其他的處理
假設長度不為一,應該是傳入多組數字
直接做比對
第三個判斷-a:傳入多組數字的核心判斷式
將tuple轉成list
用list[0]的值做為 min(max) 初始值
跑迴圈的方式修改min(max)值,最後回傳最終值
核心判斷式如下:
#最小值判斷
min = args[0]
for select in args:
if min > select:
min = select
print (min)
return min
#最大值判斷
max = args[0]
for select in args:
if max < select:
max = select
print (max)
return max
第三個判斷-b:傳入非數字值時的比對的核心判斷
在python裡,用 變數.__class__ 確認是何種型態
舉例:傳入的值是string,則判斷式為
if args[0].__class__ is str:
這裏我用另一個變數把args[0]的東西撈出來,比較方便接下來的使用
範例上看到只要是string形式的就是比ASCII碼的大小
轉ASCII碼的function我是查找這篇
ASCII 轉 int
ord('字母') = 對應int
int 轉 ASCII
chr(數字) = 對應ASCII碼
會轉碼後
再使用 第三個判斷-a的技巧,就可以比較大小值
if args[0].__class__ is str:
k = str(args[0])
min = k[0]
for select in k:
if int(ord(min)) > int(ord(select)):
min = select
print (min)
return min
第四個判斷:有key的使用
只要在第三個判斷式-a時將key值包住,用給key值得方式判斷
min = args[0]
for select in args:
if key(min) > key(select):
min = select
print (min)
return min
綜合以上,我們可以慢慢的把程式碼給完成
雖然相比其他答案算是頗冗長,好像並不需要判斷傳入何種值即可比出大小
只需要判斷傳入值是否多值或複合值即可
(但礙於是別人的答案,因此就不貼上來了)
後面做check時還有多種type的型態
因此最後還多了好幾種不同的複合值型態判斷
但不管如何,總算是成功過關了!
以下是最終的程式碼
def min(*args, **kwargs):
key = kwargs.get("key", None)
print ("key is"+str(key))
if key == None:
if len(args) is 1:
print (args[0].__class__)
if args[0].__class__ is list or args[0].__class__ is tuple or args[0].__class__ is range:
k = list(args[0])
min = k[0]
for select in k:
if min > select:
min = select
print (min)
return min
if args[0].__class__ is str:
k = str(args[0])
min = k[0]
for select in k:
if int(ord(min)) > int(ord(select)):
min = select
print (min)
return min
else:
k = list(args[0])
#print (k[0])
min = k[0]
for select in k:
if min > select:
min = select
print (min)
return min
else:
min = args[0]
for select in args:
if min > select:
min = select
print (min)
return min
else:
if len(args) is 1:
k = args[0]
min = k[0]
for select in k:
if key(min) > key(select):
min = select
print (min)
return min
else:
min = args[0]
for select in args:
if key(min) > key(select):
min = select
print (min)
return min
return None
def max(*args, **kwargs):
key = kwargs.get("key", None)
print ("key is"+str(key))
if key == None:
if len(args) is 1:
if args[0].__class__ is list or args[0].__class__ is tuple or args[0].__class__ is range:
k = list(args[0])
max = k[0]
for select in k:
if max < select:
max = select
print (max)
return max
if args[0].__class__ is str:
k = str(args[0])
max = k[0]
for select in k:
if int(ord(max)) < int(ord(select)):
max = select
print (max)
return max
else:
k = list(args[0])
#print (k[0])
max = k[0]
for select in k:
if max < select:
max = select
print (max)
return max
else:
max = args[0]
for select in args:
if max < select:
max = select
print (max)
return max
else:
if len(args) is 1:
k = list(args[0])
max = k[0]
for select in k:
if key(max) < key(select):
max = select
print (max)
return max
else:
max = args[0]
for select in args:
if key(max) < key(select):
max = select
print (max)
return max
return None
沒有留言:
張貼留言