iT邦幫忙

0

寫出一個叫do_n()函式,接受一個函式物件以及一個數字n作為引數,並呼叫給定的函式n次

程式碼如下(無遞迴版本)

def print_n(s,n):
	for i in range(n):
        print(s)
    
def do_n(f,n):
	for i in range(n):
        f()
        
do_n(print_n("hello",3),4)

預期會印出 12 個 hello。

如果是以下程式碼:

def print_n():
	for i in range(n):
        print("hello")
    
def do_n(f,n):
	for i in range(n):
        f()
        
do_n(print_n,4)

程式可以漂亮的執行,但就做不到在print_n()引入一個s字串,資料顯示,python 的函式是一級函式,如果在無遞迴版本中,do_n(f,n)函式中的f(),是空的,do_n(print_n("hello",3),4),會把 print_n("hello",3),的結果傳回來,就沒有然後了,他會不知道print_n("hello",3)意指f()。

附註:本題目在think python一書中,的第60頁

4/22:
我做出來了,

def print_n(s,n):
	for i in range(n):
		print(s)

def do_n(f,n):
	for i in range(n):
		f("hello",5)

do_n(print_n,4)

這樣就可以達成題目要求了

看更多先前的討論...收起先前的討論...
ccutmis iT邦高手 2 級 ‧ 2019-04-22 08:38:15 檢舉
這是作業對嗎...
我是參考C語言的遞廻改寫:
http://squall.cs.ntou.edu.tw/cprog/materials/recursive.html

改寫如下:
def do_n(n):
 if n==1:
  return 1
 else:
  print("hello\n %d" %(do_n(n-1)+n))
  return do_n(n-1)+n

def print_m(n,m):
 for i in range(0,m):
  do_n(n);

print_m(3,4)
froce iT邦大師 1 級 ‧ 2019-04-22 09:00:57 檢舉
他要的不應該也不用用到遞迴啦。
另外python本來速度就慢,用遞迴實現的話,函式一複雜就...
ccutmis iT邦高手 2 級 ‧ 2019-04-22 09:02:33 檢舉
感覺這種像是學生在問
小魚 iT邦大師 1 級 ‧ 2019-04-22 09:10:23 檢舉
我覺得他是在學遞迴,
終於嘗試出來了,
原來Python還可以傳function啊...
froce iT邦大師 1 級 ‧ 2019-04-22 09:16:14 檢舉
應該是作業沒錯,不過這題屬於稍微一點的中階題。
python可以做遞迴,不過真正在寫都用 generator 或是想辦法用while解決。
weiclin iT邦高手 4 級 ‧ 2019-04-22 10:26:10 檢舉
不知道題目長怎樣, 總覺的 print_n 這邊做遞迴非常多餘
froce iT邦大師 1 級 ‧ 2019-04-22 11:22:01 檢舉
應該說這整個題目在python中是不需要用到遞迴的。
只能說要看題目有沒有指定,然後課程是偏向教python還是教程設。
Kitoto iT邦新手 5 級 ‧ 2019-04-22 18:00:35 檢舉
其實,不遞迴是ok的,主要是定義一個do_n_()函數,接受一個函式物件以及一個數字作為引數,這個函式物件不管是什麼都好,當使用到do_n()時,這個函式物件必須做n次。
Kitoto iT邦新手 5 級 ‧ 2019-04-22 18:29:53 檢舉
這裡有一個問題想釐清,接受一個函式物件是指定義一個def print_n(s),s就是所謂函式物件嗎?
froce iT邦大師 1 級 ‧ 2019-04-22 19:48:39 檢舉
s當然不是函式物件...
s是函式參數。

print_n才是函式物件。

善用print、type、dir吧,他會告訴你python該怎麼寫。
froce iT邦大師 1 級 ‧ 2019-04-22 19:58:59 檢舉
然後請不要改問題,這樣後面人看到會一頭霧水。

你現在的問題我也回答了,答案就是要用裝飾器來包裝函式。
Kitoto iT邦新手 5 級 ‧ 2019-04-22 20:13:06 檢舉
ok,我懂了,原來是我對題目意思不了解,所產生的誤會。
謝謝各位的幫助,不然我不知道要卡這題多久
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

1
froce
iT邦大師 1 級 ‧ 2019-04-22 08:14:17
最佳解答
def printHello():
    print("hello")

	
def do_n(callback, n=0):
    if n >= 0:
        for i in range(0, n):
            callback()
    else:
        print("n must greater than 0")

		
do_n(printHello, 5)

如果callback要輸入函數的話,得考慮用裝飾子。
這種不用用到遞迴。

注意:

do_n(printHello, 5)
do_n(printHello(), 5)

是不同的,看清楚其中的分別。
沒加刮號的是函式本身,加了則是函式的執行結果
也就是說加了刮號的是函式return後的。

froce iT邦大師 1 級 ‧ 2019-04-22 08:32:01 檢舉

補充說明:
需要傳參數進printHello時,可參考
https://stackoverflow.com/questions/13783211/python-how-to-pass-an-argument-to-a-function-pointer-parameter
其中 lambda 的方式就是簡寫的裝飾子
partial 也很好用(其實內部也是用裝飾子實現)。

0
小魚
iT邦大師 1 級 ‧ 2019-04-22 06:38:29

Python中函式的變數可以帶入函式嗎?
這是在哪個地方看到的呢?

看更多先前的回應...收起先前的回應...
froce iT邦大師 1 級 ‧ 2019-04-22 08:16:06 檢舉

python的函式是一級公民,所以可以帶入函式。
只是他沒搞懂傳入的是函式還是執行後的結果。

小魚 iT邦大師 1 級 ‧ 2019-04-22 09:09:30 檢舉

froce
什麼叫做一級公民?

好奇試了一下,
這樣比較有遞迴的感覺

def print_n(s,n, m):
    if n > 0:
        print(s+ format(n) + "_" + format(m))
        return print_n(s, n - 1, m)   
    else: return 0
    
def do_n(f, s, n, m):
    if m > 0:
        f(s, n, m)
        return do_n(f, s, n, m-1)
    else: return 0
        
do_n(print_n, "hello", 3 ,4)

另外, 遞迴是要return值的...

froce iT邦大師 1 級 ‧ 2019-04-22 09:14:25 檢舉

看大師講應該會比我說的清楚:
python傳遞函式和js很像。
https://www.ithome.com.tw/node/75500

說真的,我很慶幸第一個語言學的是python,因為JS一半的坑在python都學過了。XD

froce iT邦大師 1 級 ‧ 2019-04-22 11:25:08 檢舉

然後這樣寫有個不太好的地方是耦合度太高,如果我今天print_n輸入參數改變,do_n那邊也得跟著變。

我要發表回答

立即登入回答