iT邦幫忙

2

【python入門教室】(3) 列表和字串也想做加法和乘法?

一般來說,我們覺得加減乘除好像是數字的專利,
然而在python中,列表和字串是有加法和乘法可以用的,
讓我們能夠更方便的操作列表和字串

譬如說如果我們希望有一個字串s
字串的內容是"Hello"連續寫五次可以怎麼寫呢?

第一個方法就是乖乖把"Hello"打五次,寫:

s="HelloHelloHelloHelloHello"

但是這樣寫有個明顯的缺點,
若你需要寫一百次"Hello"將會非常占篇幅,
並且如果想要把"Hello"寫i次(i是變數)則沒辦法處理

因此通常用for迴圈是比較好的解法:

s=""
for i in range(5):
    s = s + "Hello"
# s 的值變成"HelloHelloHelloHelloHello"

但這樣似乎仍顯囉唆,
python有很方便的運算子,加法(+)和乘法(*),
如果用在字串或列表上的意思便是「串接」和「重複」。
上述程式其實只需一行,再也不必打一堆迴圈了:

s="Hello" * 5

接著示範更多例子:

>>> "234"+"abc"
'234abc'
>>> "2"+"3"
'23'
>>> "真" * 5 + "高興見到你"
'真真真真真高興見到你'

融會貫通,加法(+)和乘法(*)亦可以用在列表上:

>>> [2,4]+[5,6,9]
[2, 4, 5, 6, 9]
>>> [1] * 6
[1, 1, 1, 1, 1, 1]

有了這樣方便直覺的運算子,
其實可以非常方便的幫助我們繪製各種有趣的圖形

範例: 階梯圖形

教大家如何在螢幕上印出階梯圖形,
我們希望在螢幕上顯示7階的階梯,如下:

*
**
***
****
*****
******
*******

大家可以先停下來想一想怎麼做。












想好了嗎?有字串的重複運算應該不會太難,
觀察圖形,我們要
在第一行印出1顆星星,
在第二行印出2顆星星,

在第i行印出i顆星星。
因此用一層for迴圈遍歷即可:

for i in range(1,8):
    print('*' * i)

範例: 金字塔圖形

教大家如何在螢幕上印出階梯圖形,
我們希望在螢幕上顯示7階的金字塔,如下:

      *
     ***
    *****
   *******
  *********
 ***********
*************

大家也可以先停下來想一想怎麼做。












我們一樣觀察圖形,
第i行需要印的空格數= 總行數 - i
第i行需要印的星星數= 2*i -1
程式如下:

for i in range(1,8):
    print(' ' * (7-i) + '*' * (2*i-1))

範例: 菱形星星

教大家如何在螢幕上印出菱形星星,
我們希望在螢幕上顯示到最寬為(7*2-1)個星星的菱形,如下圖:

      *
     ***
    *****
   *******
  *********
 ***********
*************
 ***********
  *********
   *******
    *****
     ***
      *

先停下來想一想怎麼做再往下看答案哦。












想到了嗎?
其實菱形星星我們可以想成是由前一個範例的「7階正金字塔」與一個「6階倒金字塔」組合的圖形。
那要如何印出「倒金字塔」呢?
其實就是把列印正金字塔的順序倒著印出來就行了。
這邊再教大家一個內建函數reversed(),倒轉range的值。
原本range(1,7)表示「1,2,3,4,5,6」,
加上reversed(range(1,7))就成了「6,5,4,3,2,1」

for i in reversed(range(1,7)):
    print(' ' * (6-i) + '*' * (2*i-1))

結果為一個「6階倒金字塔」:

***********
 *********
  *******
   *****
    ***
     *

因此印出整個菱形可以這樣寫:

for i in range(1,8):
    print(' ' * (7-i) + '*' * (2*i-1))
for i in reversed(range(1,7)):
    print(' ' * (7-i) + '*' * (2*i-1))

注意拼成菱形時,「6階倒金字塔」前面會多一個空格,
因此第四行應寫 print(' ' * (7-i) + '*' * (2*i-1))
而非 print(' ' * (6-i) + '*' * (2*i-1))

希望今天的內容大家覺得有趣

課後練習

今天的習題為自己出的,
暫不從CodeWar上面找

習題: 密碼不外漏

基於資安,我們知道正常在網頁上登錄頁面輸入密碼欄位時,
密碼欄位都是看不到內容的,避免旁人偷窺。
如圖示:
https://ithelp.ithome.com.tw/upload/images/20190908/20117114kYEaDuMG2E.png

請你實作一個函數hidePassword(),

def hidePassword(psd):
    return #這邊輸入你要回傳的資料

參數psd表示一個非空字串,
在函數中回傳該字串的密碼字,防止別人偷窺密碼悠。

舉例來說:

輸入: psd = "password"
輸出: "********"

輸入: psd = "123"
輸出: "***"

歡迎留言討論


1 則留言

1
Pondudu
iT邦新手 5 級 ‧ 2020-04-13 16:19:18

小馬哥您好,我的解答如下:

def hidePassword(psd):   
    return("*" * len(psd))

n = input("請輸入您的密碼")
print(hidePassword(n))

或是

def hidePassword(psd):   
    psd = input("請輸入您的密碼")
    n = "*" * len(psd)
    print(n)
    
hidePassword(n)

兩個只差在有沒有把inputprint一起打進定義裡(會建議用哪個嗎?第二個沒有return有影響嗎?)
在定義那邊卡了一下,回頭去看前面的教學才打成功,因為沒有標準答案,想請問有不同或是更簡潔的答案嗎?(總覺得我的答案有些地方是多餘的~"~)

還有一個(有點ㄅㄔ的)問題想請教,就是第二個解答,為甚麼主程式執行函數的時候不能打成hidePassword(psd)呢,就算我把定義裡的n拿掉直接print("*" * len(psd))也不能執行hidePassword(psd),執行hidePassword(n)才有效??不是有定義psd等於輸入值嗎? 被搞混了...

不好意思我毛比較多Q.Q 打擾了,祝順心:)

心原一馬 iT邦研究生 5 級 ‧ 2020-04-13 20:17:40 檢舉

哈囉,很高興你如此有學習熱忱的來發問,
您問的問題很好哦,
蠻多人也會很困惑input()print()打在函數裡面好還是外面好?
小馬推薦的解法是第一種

def hidePassword(psd):   
    return "*" * len(psd)

n = input("請輸入您的密碼")
print(hidePassword(n))

原因待小馬娓娓道來,
函數有輸出、輸入,
在小馬的比喻裡面,函數就像一台機器
而在主程式呼叫函數,就像是操作機器

這機器猶如日常生活的電鍋、販賣機…
就彷彿說「你按下電鍋按鈕(輸入),電鍋煮飯(輸出)」,
電鍋像是一個函數;
又像是「你往自動販賣機投入10塊錢,自動販賣機吐出一瓶奶茶給你」,
自動販賣機像是一個函數

所以函數做的事情其實很單純,
函數括號裡面掛的變數叫做「參數」,
定義說使用者可以丟進去的東西,
而return則是機器吐出的東西
譬如小馬定義一個「販賣機函數」:

def machine(money):
    if money==10:
        return "奶茶"
    if money==20:
        return "八寶粥"

這是在模擬當你往販賣機投入十塊錢,
販賣機會吐出一瓶奶茶給你;
當你往販賣機投入二十塊錢,
販賣機會吐出一罐八寶粥給你

這像是函數在做的事- 定義
當使用者往機器投入什麼東西時,
機器應該吐出什麼東西回來

所以這樣設計會讓函數是比較單純的,
至於input()就像是實際取得使用者丟進來的東西,
print()像是伸手去拿販賣機吐出來的東西

所以小馬是建議把input()print()
這種使用者如何操作機器的邏輯放在主程式去呼叫就好,
函數就單純的做出一台機器即可

當然可能有時候你會希望這台「機器」的功能就是要讓使用者可以在螢幕上輸入文字或直接在螢幕印出東西

不過以初學來說,
還是建議可以把定義函數想成定義一台機器,
把「操作機器」和「機器的行為」分開來寫
(小馬【python入門教室】的課後練習一律採這種形式,在函數不用print, input,只用return,這樣比較單純)

再回答你的第二個問題,
你問說為什麼寫hidePassword(psd)不行呢?
psd不是定義在函數的參數中嗎?

我想你要說的應該是「宣告」一詞,
變數需要經過宣告才能使用,
python要宣告變數需要透過=賦值才算有宣告

小馬舉個簡單的例子,
定義一台機器,你往裡面丟x元,
機器就吐2x元給你

def machine(x):
    return 2*x
    
machine(x)

那麼你在主程式裡直接呼叫machine(x)
那麼請問這時你往機器投入多少金額呢?
答案是: 沒有說
machine的邏輯只是告訴你當你輸入一個數字,
返回2倍的數字,
實際使用這個函數時,
你必須明確告訴它這個數字是多少,
譬如

def machine(x):
    return 2*x

x = 5
machine(x)

你會說: 「有啊~ 我的例子有告訴它psd是多少啊,我寫在函數裡面了」

def hidePassword(psd):   
    psd = input("請輸入您的密碼")
    
hidePassword(psd)

不知你還有印象什麼是「區域變數」與「全域變數」嗎?
你宣告在函數內的變數為「區域變數」,
因此在函數外的全域使用psd是認不得這個變數的

回覆的有點多,希望能夠幫你解惑,
也順你一切順心

Pondudu iT邦新手 5 級 ‧ 2020-04-13 20:36:49 檢舉

謝謝小馬哥!解說的超詳細,也完全回答到我糾結整個下午的疑惑>.< 哇對吼我竟然沒想到之前教過的宣告原則!(打臉) 趕快去複習才行~感謝小馬哥的耐心回答!!

心原一馬 iT邦研究生 5 級 ‧ 2020-04-13 21:00:47 檢舉

不客氣,很高興有幫你解惑哦 ^^

我要留言

立即登入留言