Sean 韋詠祥
# 語法結構
import <模組名稱>
# 舉個例子 🌰
import math
x = math.floor(3.14)
print(x)
# 語法結構
from <模組> import <模組內的東西>
from <模組> import <子模組>, <函式>, <常數>, <Class>
# 舉個例子 🌰
from string import hexdigits, capwords
print(hexdigits)
print(capwords('hello woRLD'))
# 語法結構
from <模組> import *
# 舉個例子 🌰
from math import * # 裡面包含 floor, gcd, pi 等函式及變數
n = floor(9 * pi)
print('n =', n)
m = gcd(n, 35)
print('m =', m)
# 語法結構
import <模組> as <別名>
from <模組> import <東西> as <別名>
# 舉個例子 🌰
import unicodedata as ud
from math import factorial as fact
print('Name 1:', ud.name('!')) # EXCLAMATION MARK
print('Name 2:', ud.name('😼')) # CAT FACE WITH WRY SMILE
print('5! = ', fact(5)) # 5! = 120
用 Python 計算以下數值
\[ 3^5 \text{ = ?} \\ \sqrt{2} \text{ = ?} \\ \cos (\frac{\pi}{3}) \text{ = ?} \]
Hint: 全部在 math
裡面
sqrt
, cos
, pow
, pi
建立一個名為 fibo.py
的模組檔案
# File: fibo.py def fib(n): a, b = 0, 1 while a < n: print(a, end=' ') a, b = b, a+b print()
在 VS Code 中,請按 ^N (Ctrl-N) 新增檔案
寫完後用 ^S 存檔
import fibo # 前面 fibo.py 檔名,拿掉 .py fibo.fib(20)
from fibo import fib fib(20)
在 VS Code 中,點右上角 ▷ 執行程式
在 sitcon.py
中,自己定義 fact()
函式
fact(0) = 1
fact(1) = 1 # 1
fact(2) = 2 # 2 * 1
fact(3) = 6 # 3 * 2 * 1
fact(4) = 24 # 4 * 3 * 2 * 1
fact(5) = 120 # 5 * 4 * 3 * 2 * 1
fact(6) = 720 # 6 * 5 * 4 * 3 * 2 * 1
....
fact(15) = 1307674368000 # 15 * 14 * 13 * ... * 2 * 1
Hint: 可以在 def fact()
中遞迴呼叫 fact()
函式
當有一些函式不希望被 import *
讀進來
# File: sitcon.py __all__ = ['fact'] def fact(n): pass
在 from sitcon import *
的時候
只有 __all__
裡面寫到的 fact
會被 import 進來
Note. 但可以被 import sitcon
或 from sitcon import xxx
取用
# File: sitcon.py __all__ = ['fact'] def is_negative(n): if n < 0: return True return False
def fact(n): if is_negative(n): return -1 # Error! if n > 1: return n * fact(n-1) return 1
在模組中,還有可以加上…
__author__ = 'Sean Wei'
__version__ = '1.19.2'
__license__ = 'MIT'
__status__ = 'Production'
__email__ = 'me@sean.taipei'
__copyright__ = 'Copyright 2023, SITCON Staffs'
import math
print('gcd:', math.gcd(52, 91)) # 最大公因數
print('lcm:', math.lcm(15, 21)) # 最小公倍數
print('ceil:', math.ceil(4.2)) # 上高斯(無條件進位)
print('floor:', math.floor(4.2)) # 下高斯(無條件捨去)
# 前面是函式,這兩個沒有括號的是常數
print('Natural number:', math.e) # 自然數
print('Pi:', math.pi) # 圓周率 π
import string
# 小寫字母:abcdefghijklmnopqrstuvwxyz
print('Lowercase:', string.ascii_lowercase)
# 標點符號:!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~
print('Punctuation:', string.punctuation)
# 可視字元:
print('Printable:', string.printable)
# 0123456789abcdefghijklmnopqrstuvwxyz
# ABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()
# *+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c
import sys
# 執行的參數列表
print('Arguments:', sys.argv)
# 套件路徑列表
print('Python Path:', sys.path)
# 版本資訊:3.11.4 (main, Jun 20 2023) [Clang 14.0.3]
print('Version:', sys.version)
import random
# 在 [0, 1) 之間的浮點數
print('Random number:', random.random())
# 在 [1, 5] 之間挑選一個整數
print('Lucky number:', random.randint(1, 5))
# 在 [20, 80) 之間挑選一個浮點數
print('Precipitation:', random.uniform(20, 80))
import random
# 產生內容為 [0, 1, 2, ... 48, 49] 的 list
A = [i for i in range(50)]
print('The list A:', A)
# 在 list 中隨機選一個值
print('Choice one:', random.choice(A))
# 把 A 的順序打亂
random.shuffle(A)
print('After shuffle:', A) # 現在 A 被原地修改為新的順序了
第 1 行輸入數字 N 代表長度(N ≥ 5)
第 2 行輸入 0 或 1,代表是否要包含大小寫字母
第 3 行輸入 0 或 1,代表是否要包含數字和標點符號
保證第 2 3 行不會同時為 0
使用前面提到的 strings
及 random
函式庫
每次產生 5 個長度為 N 且符合要求的隨機字串
(就算輸入要求有數字,輸出也可以沒出現數字,只要正常隨機就好)
import os
# 取得目前目錄路徑
print('Current working directory:', os.getcwd())
# 列出目錄中檔案,以根目錄為例
print('Files:', os.listdir('/'))
# 建立資料夾
os.mkdir('tmp-camp2023-data')
# 移除檔案
os.remove('trash-file')
import time
# 目前秒數:1689943200
print('Time 1:', time.time())
# 中間暫停 1.5 秒
time.sleep(1.5)
# 會比上面的秒數多 1.5 秒
print('Time 2:', time.time())
from datetime import datetime
# 結構化的目前時間:datetime(2023, 7, 21, 20, 55, 20, 123456)
t = datetime.now()
print('Datetime:', repr(t))
# 將時間格式化成指定格式:Sun, 21 Jul 2023
print('Format:', t.strftime('%a, %d %b %Y'))
# 將時間格式化成指定格式:2023-07-21 20:55:20.123456
print('Format:', t.strftime('%Y-%m-%d %H:%M:%S.%f'))
# 矩陣運算
import numpy as np
# 網頁內容請求
import requests as req
# 網頁爬蟲
import bs4.BeautifulSoup as bs
# 資料視覺化
import matplotlib.pyplot as plt
# Base64 編碼、解碼
import base64.b64encode as b64e
import base64.b64decode as b64d
import re
# 在字串中尋找
print(re.search('Camp \d+', 'SITCON Camp 2023 NCTU'))
# 需要從字串開頭就符合
print(re.match('Camp [0-9]*', 'Camp 2023 NCTU'))
# 用 ^ $ 代表開頭結尾
print(re.search('^Camp \d+$', 'SITCON Camp 2023 NCTU'))
# 尋找所有符合的結果
print(re.findall('[A-Za-z]*is', 'His name is Chris'))
在以下 ???
部分填入正確函式
並撰寫 RegEx 語句,分別從三個 txt
提取答案
import re
txt1 = 'Hello FLAG{Python} basic'
txt2 = 'xyzFLAG{an$w3R}123'
txt3 = 'owoFAAAGG{9o0D_j08!}}}()'
ans = re.???(???, txt?)
print(ans)
# Ans: FLAG{Python}, FLAG{an$w3R}, FAAAGG{9o0D_j08!}
拆成幾十個模組怎麼辦?
總不能全部丟在同個目錄吧
一個專案可能長得像這樣
telegram/ 專案頂層目錄
├── __init__.py ├── 初始化 telegram 模組的腳本
├── commands/ ├── 指令相關模組
│ ├── __init__.py │
│ ├── options.py │
│ ├── context.py │
│ └── core.py │
├── utils.py │
├── types/ ├── 專案內用到的自定義型別
│ ├── __init__.py │
│ ├── emoji.py │
│ ├── role.py │
│ └── user.py │
└── ui/ └── 介面相關程式碼
├── __init__.py
├── button.py
└── modal.py
我們可以 import 一個 .py 檔案,那資料夾呢?
因此只有包含 __init__.py
的資料夾可以被引入
此檔案中會放初始化模組用的程式碼
並且用 __all__
特殊變數,指定同目錄下要引入哪些檔案或子資料夾
# File: telegram/commands/core.py import request from telegram.ui import modal # telegram/ui/modal.py
找不到這個變數
base64.b64decode('U3Byb3V0IDIwMjI=')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'base64' is not defined
確定有 import 相關模組
import <缺少的模組>
import base64
找不到這個模組
import telebot
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'telebot'
使用 pip 安裝相應套件
$ pip install <缺少的套件>
sitconcamp@SITCON-Camp$ pip
pip: command not found
到 Python 官網安裝
先上程式碼
# File: math.py import math print(math.gcd(42, 18))
錯誤訊息
Traceback (most recent call last):
File ".../math.py", line 1, in <module>
import math
AttributeError: partially initialized module 'math' has no
attribute 'gcd' (most likely due to a circular import)
為什麼呢?
# File: main.py from foo import func1 func1()
# File: foo.py | # File: bar.py from bar import func2 | from foo import func3 def func1(): | def func2(): func2() | print('Hey there!') def func3(): | func3() print('Goodbye~') |
Traceback (most recent call last):
File ".../main.py": from foo import func1
File ".../foo.py": from bar import func2
File ".../bar.py": from foo import func3
ImportError: cannot import name 'func3' from
partially initialized module 'foo' (most likely
due to a circular import) (.../foo.py)
# ✅ 正確寫法
import os
import sys
# ❌ 錯誤示範
import sys, os
# ✅ 這樣也是正確的
from subprocess import Popen, PIPE
#!/usr/bin/env python
"""Script for SITCON Camp Demo
Meow meow meow meow meow
"""
import os
import math
_USAGE = 'Just run this script. :)'
import os
import string
from time import sleep
from datetime import datetime
import telebot
import requests as req
from telebot.callback_data import CallbackData
import camputils
__future__
等特殊 import"""This is the example module.
This module does stuff.
"""
from __future__ import annotations
__all__ = ['fact', 'exgcd', 'c']
__version__ = '0.1'
__author__ = 'SITCON 2023 Team'
import os
import sys
import datetime
t = datetime.datetime.now()
print('Case A:', t)
print('Case B:', str(t))
print('Case C:', repr(t))
s = repr(t) # 取得給直譯器看的 representation 格式
type(s) # 確認得到的是個字串 (str)
n = eval(s) # 把 str 轉換回 datetime
type(n) # 確認轉換成功
import this
# The Zen of Python, by Tim Peters
#
# Beautiful is better than ugly.
# Explicit is better than implicit.
# Simple is better than complex.
# Complex is better than complicated.
# Flat is better than nested.
# Sparse is better than dense.
# Readability counts.
# [...]
import __hello__
# Hello world!
from __future__ import braces
# SyntaxError: not a chance
# xkcd
import antigravity
# Geohashing: https://xkcd.com/426/
antigravity.geohash(24.787, 120.997, b'Meow')
投影片連結:https://hackmd.io/@Sean64/py-module-sitcon2023