Sean Wei
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- type: slide tags: presentation title: Class - 資訊之芽 2023 Python 語法班 description: Sean 韋詠祥 / 2023-05-07 14:15 / 什麼是 Class / 繼承 / attribute 層級比較 / 常見錯誤 / Private Variable / Decorator / dataclass --- # Class 資訊之芽 2023 Python 語法班 Author: Sean 韋詠祥 Note: 日期:2023-05-07 課程時間:14:15 - 15:30 大作業寫過 class 了 ### Time 14:15 開場 14:25 什麼是 Class 14:30 名詞解釋 14:35 課堂練習(一) 14:50 繼承 14:55 什麼是 `super()` 15:00 attribute 層級比較 15:10 常見錯誤 15:15 魔術方法 15:20 課堂練習(二) 15:30 參考資料 / 延伸閱讀 ---- ## 在開始之前 - 打開這份簡報 - https://hackmd.io/@Sean64/py-class - 開啟 [程式碼小抄](https://hackmd.io/@Sean64/py-class-codes) 頁面 - 準備好 VS Code 環境 ---- ## 如果我們想要紀錄.... ```python speaker_name = 'Sean Wei' speaker_birthday = 'June' speaker_skills = ['Cybersecurity', 'Diving'] ``` ---- ## 加上第二個人 ```python speaker1_name = 'Sean Wei' speaker1_birthday = 'June' speaker1_skills = ['Cybersecurity', 'Diving'] ``` ```python speaker2_name = 'William Mou' speaker2_birthday = 'October' speaker2_skills = ['Photography', 'Supercomputing'] ``` ---- ## 如果還有第三個人 ```python speaker1_name = 'Sean Wei' speaker1_birthday = 'June' speaker1_skills = ['Cybersecurity', 'Diving'] ``` ```python speaker2_name = 'William Mou' speaker2_birthday = 'October' speaker2_skills = ['Photography', 'Supercomputing'] ``` ```python speaker3_name = 'Sirius Koan' speaker3_birthday = 'July' speaker3_skills = ['Softball', 'Mail'] ``` 越來越多,有點麻煩... ---- ## 透過 dict 化簡 ```python speaker1 = { 'name': 'Sean Wei', 'birthday': 'June', 'skills': ['Cybersecurity', 'Diving'] } ``` ```python speaker2 = { 'name': 'William Mou', 'birthday': 'October', 'skills': ['Photography', 'Supercomputing'] } ``` ```python speaker3 = { 'name': 'Sirius Koan', 'birthday': 'July', 'skills': ['Softball', 'Mail'] } ``` --- ## 什麼是 Class - 中文:類別 - 自己創造一個物件(資料型態) - 把函式跟變數結合的工具 ```python # 定義方式 class Speaker: pass ``` ---- ## 如何使用 Class 跟函式定義的方式很像 ```python class Speaker: pass ``` ```python speaker1.name = 'Sean Wei' speaker1.birthday = 'June' speaker1.skills = ['Cybersecurity', 'Diving'] ``` ```python speaker2.name = 'William Mou' speaker2.birthday = 'October' speaker2.skills = ['Photography', 'Supercomputing'] ``` 看起來似乎沒有比較簡潔 ---- ## 正確的寫法 ```python class Speaker: def __init__(self, name, birthday, skills): self.name = name self.birthday = birthday self.skills = skills ``` ```python speaker1 = Speaker('Sean Wei', 'June', ['Cybersecurity', 'Diving']) ``` ```python speaker2 = Speaker('William Mou', 'October', ['Photography', 'Supercomputing']) ``` ```python speaker3 = Speaker('Sirius Koan', 'July', ['Softball', 'Mail']) ``` ---- ## 名詞解釋 - `method` 方法:class 裡面的 function - `instance` 實體:依照 class 做出來的物件 - `attribute` 屬性:class 裡面的變數 ---- ## `self` - class 中 method 的參數至少要有 self - 決定要設定哪一個物件 ---- ## `__init__()` - class 中一個特殊的 method - 是一個 constructor 建構子,初始化的時候用 - 使用 `obj = classname()` 建構時會被呼叫 - 一定要有 self 做為參數 ---- ## 課堂練習(一) 幫 `class Speaker` 實作 `learn()` 函式 讓講師向另一位講師學習相關技能 ```python class Speaker: def __init__(self, name, birthday, skills): self.name = name self.birthday = birthday self.skills = skills def learn(self, teacher): print(f'{self=}, {self.skills=}') print(f'{teacher=}, {teacher.skills=}') # Write your code here ``` ```python speaker1 = Speaker('Sean Wei', 'June', ['Cybersecurity', 'Diving']) speaker2 = Speaker('William Mou', 'October', ['Photography', 'Supercomputing']) speaker1.learn(speaker2) ``` Note: Answer: `self.skills.extend(teacher.skills)` --- ## 繼承 Inheritance ---- ## 有兩種身份 分別定義 Student 及 Employee ```python class Student: def __init__(self, name, age, student_id): self.name = name self.age = age self.student_id = student_id def say_hi(): print(f'Hello, I am {name}!') ``` ```python class Employee: def __init__(self, name, age, employee_id): self.name = name self.age = age self.employee_id = employee_id def say_hi(): print(f'Hello, I am {name}!') ``` ---- ## 抽取重複部分 核心概念:DRY(Don’t Repeat Yourself) ```python class Person: def __init__(self, name, age): self.name = name self.age = age def say_hi(): print(f'Hello, I am {name}!') ``` ```python class Student(Person): def __init__(self, name, age, student_id): super().__init__(name, age) self.student_id = student_id ``` ```python class Employee(Person): def __init__(self, name, age, employee_id): super().__init__(name, age) self.employee_id = employee_id ``` ---- ## 什麼是 `super()` - 代表父類別 - 透過 `super()` 執行上層函式 - 放在函式開頭、中間、結尾都可以 ---- ## 語法結構 ```python class NormalClass: pass class NormalClass(): pass ``` ```python class DerivedClass(BaseClass): pass class DerivedClass(moduleName.BaseClass): pass ``` ```python class DerivedClass(Base1, Base2, Base3): pass ``` ---- ## 對於多層繼承的 super() 呢? ```python class First: def __init__(self): print('Initializing first class') # super().__init__() # no need ``` ```python class Second(First): def __init__(self): print('Initializing second class') super().__init__() ``` ```python class Third(Second): def __init__(self): print('Initializing third class') super().__init__() ``` ```python foo = Third() ``` ---- ## 繼承多個類別的 super() ```python class Foo: def __init__(self): print('Initializing foo class') super().__init__() # note here ``` ```python class Bar: def __init__(self): print('Initializing bar class') # super().__init__() # no need ``` ```python class Test(Foo, Bar): def __init__(self): print('Initializing test class') super().__init__() ``` ```python baz = Test() ``` ---- ## 特殊變數 `__mro__` Method Resolution Order ```python print(Student.__mro__) ``` ```python print(Third.__mro__) ``` ```python print(Test.__mro__) ``` --- ## attribute 層級比較 class-level vs instance-level ---- ## 建立 Phone 類別 ```python class Phone: pwd = '0000' foo = Phone() bar = Phone() ``` ```python print(f'{Phone.pwd=}, {foo.pwd=}, {bar.pwd=}') ``` Output: `Phone.pwd='0000', foo.pwd='0000', bar.pwd='0000'`<!-- .element: class="fragment" data-fragment-index="1" --> ---- ## 修改 foo 密碼 ```python foo.pwd = '1234' print(f'{Phone.pwd=}, {foo.pwd=}, {bar.pwd=}') ``` Output: `Phone.pwd='0000', foo.pwd='1234', bar.pwd='0000'`<!-- .element: class="fragment" data-fragment-index="1" --> ---- ## 修改 Phone 密碼 ```python Phone.pwd = '5678' print(f'{Phone.pwd=}, {foo.pwd=}, {bar.pwd=}') ``` Output: `Phone.pwd='5678', foo.pwd='1234', bar.pwd='5678'`<!-- .element: class="fragment" data-fragment-index="1" --> Note: 問:為什麼 foo 沒有跟著改 ---- ## 查看 attribute 可以用 `vars()` 函式 ```python print(vars(Phone)) # {'__module__': '__main__', # 'pwd': '5678', '__dict__': ....} print(vars(foo)) # {'pwd': '1234'} print(vars(bar)) # {} ``` 或是透過 `__dict__` 取得 ```python # Same as above print(Phone.__dict__) print(foo.__dict__) print(bar.__dict__) ``` ---- ## 設定顏色 ```python Phone.color = 'blue' print(f'{Phone.color=}, {foo.color=}, {bar.color=}') ``` Output: `Phone.color='blue', foo.color='blue', bar.color='blue'`<!-- .element: class="fragment" data-fragment-index="1" --> ---- ## 設定價格 ```python foo.price = 34_900 print(f'{Phone.price=}, {foo.price=}, {bar.price=}') ``` Output: `AttributeError`<!-- .element: class="fragment" data-fragment-index="1" --> --- ## 常見錯誤 為什麼我的 list 不乖 Note: 9.3.5. Class and Instance Variables ---- ## 直觀的寫法 ```python class Person: skills = [] # Note here def learn(self, skill): self.skills.append(skill) ``` ```python sean = Person() sean.learn('Cybersecurity') sean.learn('Diving') print(f'{sean.skills=}') ``` ```python mou = Person() mou.learn('Photography') mou.learn('Supercomputing') print(f'{mou.skills=}') ``` ---- ## 正確寫法 ```python class Person: def __init__(self): # creates a new empty list for each person self.skills = [] def learn(self, skill): self.skills.append(skill) ``` ```python sean = Person() sean.learn('Cybersecurity') sean.learn('Diving') print(f'{sean.skills=}') ``` ```python mou = Person() mou.learn('Photography') mou.learn('Supercomputing') print(f'{mou.skills=}') ``` --- ## 魔術方法 Magic methods ---- ## 讓我們為食物建立 class ```python class Food: def __init__(self, price, calorie): self.price = price # Unit: NTD self.calorie = calorie # Unit: kcal ``` ```python chicken_nuggets = Food(65, 260) french_fries = Food(65, 530) oreo_flurry = Food(55, 360) corn_soup = Food(40, 90) ``` ---- ## 印出價格、熱量 ```python class Food: # ... def __str__(self): return 'price and calorie is xxx' # 小練習 ``` ```python # 記得先重新執行 xxx = Food(x, x) 語句 print(french_fries) # price = 65 NTD, calorie = 260 kcal ``` ---- ## 把食物混在一起 ```python class Food: # ... def __add__(self, other): price = 0 # 請完成 calorie = 0 # 請完成 mixture = Food(price, calorie) return mixture ``` ```python # 記得先重新執行 xxx = Food(x, x) 語句 oreo_nuggets = oreo_flurry + chicken_nuggets print(oreo_nuggets) # price = 120 NTD, calorie = 620 kcal ``` ---- ## 課堂練習(二) 把 `class Food` 實作得更完整 ```python class Food: # ... def __mul__(self, num): pass # 計算 num 份食物的價格、熱量 def __truediv__(self, num): pass # 平分給 num 個人後每份長怎樣 ``` ```python def __eq__(self, other): pass # 比較「💲價格」相不相同,暫時無視熱量 def __gt__(self, other): pass # 比較「🔥熱量」是否更高,暫時無視價格 # (optional) 針對「💲價格」,除了 eq 相等之外,實作 ne 不相等 # (optional) 針對「🔥熱量」,除了 gt 外,實作 lt 小於、ge、le ``` --- # Thanks 投影片連結:https://hackmd.io/@Sean64/py-class <!-- .element: class="r-fit-text" --> <br> [![CC-BY](https://mirrors.creativecommons.org/presskit/buttons/88x31/png/by.png)](https://creativecommons.org/licenses/by/4.0/deed.zh_TW) ###### 這份投影片以 [創用 CC - 姓名標示](https://creativecommons.org/licenses/by/4.0/deed.zh_TW) 授權公眾使用,原始碼及講稿請見 [此連結](https://hackmd.io/@Sean64/py-class/edit)。 ---- ## 參考資料 / 延伸閱讀 - 歷年資芽講義:[Py 2022](https://sprout.tw/py2022/slides), [Py 2021](https://sprout.tw/py2021/#!slides.md) - [三分鐘學會 Class 運用](https://youtu.be/dQw4w9WgXcQ) - [關於物件導向的繼承](https://medium.com/seaniap/py-f93028056d9b) - PyDoc: [Class tutorial](https://docs.python.org/3/tutorial/classes.html), [Class reference](https://docs.python.org/3/reference/compound_stmts.html#class-definitions) - Private Variables - `@Decorator` - `@dataclass`

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully