Stanford Python程式課 - 第三週
上週 (第二週) 的課程主要為Python入門,介紹Expressions運算式、Control flow流程控制等,從While/If、Booleans、For Loops等,建立完整的 Python 核心基礎。
課程第三週學習目標
- Lesson 7: Functions Revisited 複習Functions
- Lesson 8: Core Complete 完整核心
- Lesson 9: Images 影像處理
Code in Place第三週課程 Lesson 7: Functions |
Lesson 7: Functions Revisited
學習重點
- 如何定義function
- 透過參數輸入資料
- 回傳資料
Functions are Like Toasters!
使用「烤麵包機」,不需要知道「烤麵包機」是怎麼製造的 = 使用「別人寫的Function」,不需要知道「別人寫的Function」是怎麼完成的
使用「烤麵包機」,需要知道「烤麵包機」只接受什麼樣的麵包 = 使用「別人寫的Function」,需要知道「別人寫的Function」只接受什麼樣的參數
使用「烤麵包機」,知道「烤麵包機」會回傳烤好的麵包 = 使用「別人寫的Function」,知道「別人寫的Function」會回傳什麼樣的資料
YouTube課程影片
Lecture 7-1: Recap and Show
Lecture 7-2: Toaster are Fns
Lecture 7-3: Anatomy of a Fn
Lecture 7-4: Many Examples
Lecture 7-5: Decomp Show
點我下載課程講義
延伸閱讀Python Reader
Lesson 8: Core Complete完整核心
本節課程是最完整的Python核心基礎,包含參數、流程控制、Function間資訊傳遞,以及很重要的Doctest!
下面Lecture example程式碼中的Factorial、Doctest都有Doctest使用的範例可以參考。
學習重點
- Trace control flow 追蹤控制流程
- Doctest 除錯驗證
- Practice practice practice 不斷練習
Code in Place Lesson 8: Core Complete學習目標 |
YouTube課程影片
Lecture 8-1: Intro
Lecture 8-2: Sentiment
Lecture 8-3: Factorial
Lecture 8-4: Add_five
Lecture 8-5: Doctests
Lecture 8-6: Rock Paper Scissors
點我下載課程講義
延伸閱讀Python Reader
Lecture Examples
Sentiment Analysis程式
import nltk.sentiment analyzer = nltk.sentiment.SentimentIntensityAnalyzer() def main(): while True: user_text = input('? ') score = get_sentiment(user_text) reaction = get_reaction(score) print(reaction) print(score) print('') def get_reaction(score): """ Parameter score: a float between -1 and +1 Return: An emoji as a string! """ if score > 0.5: return "🥰" if score > 0: return "🙂" if score == 0: return "😶" if score < -0.5: return "😢" if score < 0: return "😟" def get_sentiment(user_text): """ Parameter user_text: any text (string) Return: a sentiment score between -1 and +1 (float) """ # 1. pass the text into the analyzer.polarity_scores function, part of the nltk package scores = analyzer.polarity_scores(user_text) # 2. extract the sentiment score. Scores is a "dictionary" (covered on May 17th) sentiment_score = scores['compound'] return sentiment_score if __name__ == '__main__': main()
Factorial程式
# Constant – visible to all functions MAX_NUM = 9 def main(): # repeat for several values! for i in range(MAX_NUM+1): print(i, factorial(i)) def factorial(n): """ Calculates n factorial. 5 factorial is 5 * 4 * 3 * 2 * 1 >>> factorial(6) 720 >>> factorial(5) 120 >>> factorial(4) 24 >>> factorial(3) 6 >>> factorial(1) 1 >>> factorial(0) 1 """ answer = 1 for i in range(1,n+1): answer *= i return answer if __name__ == '__main__': main()
Doctest程式
""" Example of Doctest """ def main(): year = int(input("Enter a year to check leap year: ")) if is_leap_year(year): print("Year "+str(year)+" is a leap year") else: print("Year "+str(year)+" is NOT a leap year") def is_divisible(a, b): """ >>> is_divisible(20, 4) True >>> is_divisible(12, 7) False >>> is_divisible(10, 10) True """ return a % b == 0 def is_leap_year(year): """ Returns Boolean indicating if given year is a leap year. It is a leap year if the year is: * divisible by 4, but not divisible by 100 OR * divisible by 400 Doctests: >>> is_leap_year(2001) False >>> is_leap_year(2020) True >>> is_leap_year(2000) True >>> is_leap_year(1900) False """ # if the year is divisible by 400, it is a leap year! if is_divisible(year, 400): return True # other wise its a leap year if its divisible by 4 and not 100 return is_divisible(year, 4) and not is_divisible(year, 100) if __name__ == '__main__': main()
Lesson 9: Images
Instagram其實是創辦人在CS106課程中學習了程式處理影像,才激發了創辦Instagram的動機!
學習重點
- 了解影像如何在程式中呈現
- 學習SimpleImage Library
- 撰寫操控影像的程式
YouTube課程影片
Lecture 9-1: Intro
Lecture 9-2: SimpleImage
Lecture 9-3: Image Examples
Lecture 9-4: Greenscreen
Lecture 9-5: Mirror
Lecture 9-6: Wrap
Lecture 9-7: Responsibility
點我下載課程講義
延伸閱讀Python Reader
安裝Pillow、下載 simpleimage.py
提供 Stanford 的 simpleimage.py 程式,請自行選取複製後儲存成 simpleimage.py ,在Pycharm ((IDE) 中執行課程的範例需要
- 安裝Pillow library
- 將 simpleimage.py 檔案放在PyCharm (IDE) 的project目錄內
延伸閱讀:Stanford Code in Place線上Python入門課程 - Week 2
延伸閱讀:Stanford Code in Place線上Python入門課程 - Week 1
延伸閱讀:從Stanford學習免費、但值一萬美元的程式設計課
Pillow安裝方式,資料來源:Code in Place Lesson 9 Lecture Slides |
simpleimage.py:
#!/usr/bin/env python3 """ Stanford CS106AP SimpleImage Written by Nick Parlante, Sonja Johnson-Yu, and Nick Bowman. -7/2019 version, has file reading, pix, foreach, hidden get/setpix SimpleImage Features: Create image: image = SimpleImage.blank(400, 200) # create new image of size image = SimpleImage('foo.jpg') # create from file Access size image.width, image.height Get pixel at x,y pix = image.get_pixel(x, y) # pix is RGB tuple like (100, 200, 0) Set pixel at x,y image.set_pixel(x, y, pix) # set data by tuple also Get Pixel object at x,y pixel = image.get_pixel(x, y) pixel.red = 0 pixel.blue = 255 Show image on screen image.show() The main() function below demonstrates the above functions as a test. """ import sys # If the following line fails, "Pillow" needs to be installed from PIL import Image def clamp(num): """ Return a "clamped" version of the given num, converted to be an int limited to the range 0..255 for 1 byte. """ num = int(num) if num < 0: return 0 if num >= 256: return 255 return num class Pixel(object): """ A pixel at an x,y in a SimpleImage. Supports set/get .red .green .blue and get .x .y """ def __init__(self, image, x, y): self.image = image self._x = x self._y = y def __str__(self): return 'r:' + str(self.red) + ' g:' + str(self.green) + ' b:' + str(self.blue) # Pillow image stores each pixel color as a (red, green, blue) tuple. # So the functions below have to unpack/repack the tuple to change anything. @property def red(self): return self.image.px[self._x, self._y][0] @red.setter def red(self, value): rgb = self.image.px[self._x, self._y] self.image.px[self._x, self._y] = (clamp(value), rgb[1], rgb[2]) @property def green(self): return self.image.px[self._x, self._y][1] @green.setter def green(self, value): rgb = self.image.px[self._x, self._y] self.image.px[self._x, self._y] = (rgb[0], clamp(value), rgb[2]) @property def blue(self): return self.image.px[self._x, self._y][2] @blue.setter def blue(self, value): rgb = self.image.px[self._x, self._y] self.image.px[self._x, self._y] = (rgb[0], rgb[1], clamp(value)) @property def x(self): return self._x @property def y(self): return self._y # color tuples for background color names 'red' 'white' etc. BACK_COLORS = { 'white': (255, 255, 255), 'black': (0, 0, 0), 'red': (255, 0, 0), 'green': (0, 255, 0), 'blue': (0, 0, 255), } class SimpleImage(object): def __init__(self, filename, width=0, height=0, back_color=None): """ Create a new image. This case works: SimpleImage('foo.jpg') To create a blank image use SimpleImage.blank(500, 300) The other parameters here are for internal/experimental use. """ # Create pil_image either from file, or making blank if filename: self.pil_image = Image.open(filename).convert("RGB") if self.pil_image.mode != 'RGB': raise Exception('Image file is not RGB') self._filename = filename # hold onto else: if not back_color: back_color = 'white' color_tuple = BACK_COLORS[back_color] if width == 0 or height == 0: raise Exception('Creating blank image requires width/height but got {} {}' .format(width, height)) self.pil_image = Image.new('RGB', (width, height), color_tuple) self.px = self.pil_image.load() size = self.pil_image.size self._width = size[0] self._height = size[1] self.curr_x = 0 self.curr_y = 0 def __iter__(self): return self def __next__(self): if self.curr_x < self.width and self.curr_y < self.height: x = self.curr_x y = self.curr_y self.increment_curr_counters() return Pixel(self, x, y) else: self.curr_x = 0 self.curr_y = 0 raise StopIteration() def increment_curr_counters(self): self.curr_x += 1 if self.curr_x == self.width: self.curr_x = 0 self.curr_y += 1 @classmethod def blank(cls, width, height, back_color=None): """Create a new blank image of the given width and height, optional back_color.""" return SimpleImage('', width, height, back_color=back_color) @classmethod def file(cls, filename): """Create a new image based on a file, alternative to raw constructor.""" return SimpleImage(filename) @property def width(self): """Width of image in pixels.""" return self._width @property def height(self): """Height of image in pixels.""" return self._height def get_pixel(self, x, y): """ Returns a Pixel at the given x,y, suitable for getting/setting .red .green .blue values. """ if x < 0 or x >= self._width or y < 0 or y >= self.height: e = Exception('get_pixel bad coordinate x %d y %d (vs. image width %d height %d)' % (x, y, self._width, self.height)) raise e return Pixel(self, x, y) def set_pixel(self, x, y, pixel): if x < 0 or x >= self._width or y < 0 or y >= self.height: e = Exception('set_pixel bad coordinate x %d y %d (vs. image width %d height %d)' % (x, y, self._width, self.height)) raise e self.px[x, y] = (pixel.red, pixel.green, pixel.blue) def set_rgb(self, x, y, red, green, blue): """ Set the pixel at the given x,y to have the given red/green/blue values without requiring a separate pixel object. """ self.px[x, y] = (red, green, blue) def _get_pix_(self, x, y): """Get pix RGB tuple (200, 100, 50) for the given x,y.""" return self.px[x, y] def _set_pix_(self, x, y, pix): """Set the given pix RGB tuple into the image at the given x,y.""" self.px[x, y] = pix def show(self): """Displays the image using an external utility.""" self.pil_image.show() def make_as_big_as(self, image): """Resizes image to the shape of the given image""" self.pil_image = self.pil_image.resize((image.width, image.height)) self.px = self.pil_image.load() size = self.pil_image.size self._width = size[0] self._height = size[1] def main(): """ main() exercises the features as a test. 1. With 1 arg like flowers.jpg - opens it 2. With 0 args, creates a yellow square with a green stripe at the right edge. """ args = sys.argv[1:] if len(args) == 1: image = SimpleImage.file(args[0]) image.show() return # Create yellow rectangle, using foreach iterator image = SimpleImage.blank(400, 200) for pixel in image: pixel.red = 255 pixel.green = 255 pixel.blue = 0 # for pixel in image: # print(pixel) # Set green stripe using pix access. pix = image._get_pix_(0, 0) green = (0, pix[1], 0) for x in range(image.width - 10, image.width): for y in range(image.height): image._set_pix_(x, y, green) image.show() if __name__ == '__main__': main()
Lecture Examples
Imageexampless.py
""" This program contains several examples of functions that manipulate an image to show how the SimpleImage library works. """ from simpleimage import SimpleImage def darker(image): """ Makes image passed in darker by halving red, green, blue values. Note: changes in image persist after function ends. """ # Demonstrate looping over all the pixels of an image, # changing each pixel to be half its original intensity. for pixel in image: pixel.red = pixel.red // 2 pixel.green = pixel.green // 2 pixel.blue = pixel.blue // 2 def red_channel(filename): """ Reads image from file specified by filename. Changes the image as follows: For every pixel, set green and blue values to 0 yielding the red channel. Return the changed image. """ image = SimpleImage(filename) for pixel in image: pixel.green = 0 pixel.blue = 0 return image def compute_luminosity(red, green, blue): """ Calculates the luminosity of a pixel using NTSC formula to weight red, green, and blue values appropriately. """ return (0.299 * red) + (0.587 * green) + (0.114 * blue) def grayscale(filename): """ Reads image from file specified by filename. Change the image to be grayscale using the NTSC luminosity formula and return it. """ image = SimpleImage(filename) for pixel in image: luminosity = compute_luminosity(pixel.red, pixel.green, pixel.blue) pixel.red = luminosity pixel.green = luminosity pixel.blue = luminosity return image def main(): """ Run your desired image manipulation functions here. You should store the return value (image) and then call .show() to visualize the output of your program. """ flower = SimpleImage('flower.png') flower.show() darker(flower) flower.show() red_flower = red_channel('flower.png') red_flower.show() grayscale_flower = grayscale('flower.png') grayscale_flower.show() if __name__ == '__main__': main()
greenscreen.py
""" This program shows an example of "greenscreening" (actually "redscreening" in this case). This is where we replace the pixels of a certain color intensity in a particular channel (here, we use red) with the pixels from another image. """ from simpleimage import SimpleImage INTENSITY_THRESHOLD = 1.6 def redscreen(main_filename, back_filename): """ Implements the notion of "redscreening". That is, the image in the main_filename has its "sufficiently red" pixels replaced with pixel from the corresponding x,y location in the image in the file back_filename. Returns the resulting "redscreened" image. """ image = SimpleImage(main_filename) back = SimpleImage(back_filename) for pixel in image: average = (pixel.red + pixel.green + pixel.blue) // 3 # See if this pixel is "sufficiently" red if pixel.red >= average * INTENSITY_THRESHOLD: # If so, we get the corresponding pixel from the # back image and overwrite the pixel in # the main image with that from the back image. x = pixel.x y = pixel.y image.set_pixel(x, y, back.get_pixel(x, y)) return image def main(): """ Run your desired image manipulation functions here. You should store the return value (image) and then call .show() to visualize the output of your program. """ original_stop = SimpleImage('stop.png') original_stop.show() original_leaves = SimpleImage('leaves.png') original_leaves.show() stop_leaves_replaced = redscreen('stop.png', 'leaves.png') # stop_leaves_replaced = redscreen(original_stop, original_leaves) stop_leaves_replaced.show() if __name__ == '__main__': main()
mirror.py
""" File: mirror.py --------------- This program shows an example of creating an image that shows an original image and its mirror reflection in a new image. """ from simpleimage import SimpleImage def mirror_image(filename): """ Read an image from the file specified by filename. Returns a new images that includes the original image and its mirror reflection. Returns the resulting "redscreened" image. """ image = SimpleImage(filename) width = image.width height = image.height # Create new image to contain mirror reflection mirror = SimpleImage.blank(width * 2, height) for y in range(height): for x in range(width): pixel = image.get_pixel(x, y) mirror.set_pixel(x, y, pixel) mirror.set_pixel((width * 2) - (x + 1), y, pixel) return mirror def main(): """ Run your desired image manipulation functions here. You should store the return value (image) and then call .show() to visualize the output of your program. """ original = SimpleImage('burrito.jpg') original.show() mirrored = mirror_image('burrito.jpg') mirrored.show() if __name__ == '__main__': main()
2 comments
您好,看了您的文章加上code in place的課程收穫良多,但現在課程已經結束,無法再報名取得Ed的帳號,前兩週您的的文章裡有看到作業可以練習,week3就沒有看到assignments的題目,不知是否方便提供呢?謝謝!
回覆刪除抱歉先前沒看到留言,Assignment並不是每週課程都有,剛剛回去看了Code in Place網頁,一共只有三個Assignment,加最後的Final Project,Assignment 3是在 Week 5的課程文章內喔
刪除Final Project沒有限定題目,是學生自由發揮,最後的連結在此 https://codeinplace.stanford.edu/2021/showcase,有興趣可以參考大家的創作