<jupyter_start><jupyter_text>![image](https://www.python.org/static/img/python-logo.png) 亞洲大學基礎程式設計教材(AUP110-Fundamentals of Programming)![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)  Week15-類別(Class)的宣告和繼承https://docs.python.org/3/tutorial/classes.htmlClass 提供了一種結合資料與功能的手段。建立一個 class 將會新增一個物件的型別 (type)，並且允許建立該型別的新實例 (instance)。每一個 class 實例可以擁有一些維持該實例狀態的屬性 (attribute)。Class 實例也可以有一些（由其 class 所定義的）method（方法），用於修改該實例的狀態。與其他程式語言相比，Python 的 class 機制為 class 增加了最少的新語法跟語意。他混合了 C++ 和 Modula-3 的 class 機制。Python 的 class 提供了所有物件導向程式設計 (Object Oriented Programming) 的標準特色：class 繼承機制允許多個 base class（基底類別），一個 derived class（衍生類別）可以覆寫 (override) 其 base class 的任何 method，且一個 method 可以用相同的名稱呼叫其 base class 的 method。物件可以包含任意數量及任意種類的資料。如同模組一樣，class 也具有 Python 的動態特性：他們在執行期 (runtime) 被建立，且可以在建立之後被修改。物件導向程式設計就必須對類別(Class)及物件(Object)等有一些基本的了解，包含了：類別(Class)、物件(Object)、屬性(Attribute)、建構式(Constructor)、方法(Method)  Topic 1(主題1)-Class definition（類別定義）  Step 1: 類別的定義(definition)-屬性(property)按慣例，命名 class 用 UpperCamelCase（駝峰式大小寫）<jupyter_code>class MyClass:
    x = 5
    y =11

p1 = MyClass() #建立 MyClass 的一個新實例，並將此物件指派給區域變數 p1。
print(p1.x, p1.y)
del p1<jupyter_output><empty_output><jupyter_text>Step 2: 類別的初始值-$__init__()$實例化運算（「呼叫」一個 class 物件）會建立一個空的物件。許多 class 在建立物件時有著自訂的特定實例初始狀態。因此，class 可以定義一個名為 $__init__()$ 的特別 method。<jupyter_code>class Person:
  def __init__(self, name, age):#建構式(Constructor)
    self.name = name
    self.age = age

p2 = Person("Hwang", 52) 
print(p2.name, p2.age)<jupyter_output><empty_output><jupyter_text>Step 3: 類別的成員函數定義<jupyter_code>class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def foo(self):
    print("Hello my name is " + self.name)

p2 = Person("Hwang", 52)
p2.foo()<jupyter_output><empty_output><jupyter_text>Step 4: 作用域 (Scope) 及命名空間 (Namespace)<jupyter_code>def scope_test():
    def do_local():
        spam = "local spam"

    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal spam"

    def do_global():
        global spam
        spam = "global spam"

    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:", spam)
    do_global()
    print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)<jupyter_output><empty_output><jupyter_text>Topic 2(主題2)-Class Inheritance (類別繼承)derived class（衍生類別）繼承base class（基礎類別）  Step 5: derived class（衍生類別）<jupyter_code>class Person:
    name = "AAA"
    age = 20

class Police(Person):
    rank = "Sergeant"

p3 = Police()
print(p3.name, p3.age, p3.rank)
class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

class Police(Person):
  def __init__(self, name, age, rank):
    Person.__init__(self, name, age)
    self.rank = rank

p3 = Police("Skyman", 51, "lieutenant")
print(p3.name, p3.age, p3.rank)<jupyter_output><empty_output><jupyter_text>Step 6: super()函數<jupyter_code>class Person:
    name = "AAA"
    salary = 2000
    def print_salary(self):
         return(salary)

class Police(Person):
    rank = "Sergeant"
    salary = 3000
    def print_annual_salary_a(self):
         print(self.salary*12)    
    def print_annual_salary_b(self):
         print(super().salary*12)  

p5 = Police()
p5.print_annual_salary_a()
p5.print_annual_salary_b()<jupyter_output><empty_output><jupyter_text>Topic 3(主題3)-decorator（裝飾器）由於 Python 的基本語法為了簡單好用簡潔，讓 Python 的語法變得愈來愈繁複。裝飾器是一個函式，它會回傳另一個函式，通常它會使用 @wrapper 語法，被應用為一種函式的變換 (function transformation)。裝飾器的常見範例是 classmethod() 和 staticmethod()。裝飾器語法只是語法糖。以下兩個函式定義在語義上是等效的：```def f(...):    ...f = staticmethod(f)@staticmethoddef f(...):    ...```Python Decorator 機制是為了讓你在定義函式與方法之後，可以用簡單的方式來修改並重新定義＂裝飾＂什麼：* 用了Decorator可以方便延伸原本已完成的function* 延伸時使程式碼簡潔  Step 7:裝飾詞(Decorator)延伸原本已完成的function<jupyter_code>def my_decorator(func):
    print('In A')
    return func

@my_decorator
def my_func():
    print('In B')

my_func()<jupyter_output><empty_output><jupyter_text>Step 8:裝飾詞(Decorator)延伸時使程式碼簡潔```def requires_admin(fn):    def ret_fn(*args,**kwargs):        lPermissions = get_permissions(current_user_id())        if 'administrator' in lPermissions:            return fn(*args,**kwargs)        else:            raise Exception("Not allowed")    return ret_fndef requires_logged_in(fn):    def ret_fn(*args,**kwargs):        lPermissions = get_permissions(current_user_id())        if 'logged_in' in lPermissions:            return fn(*args,**kwargs)        else:            raise Exception("Not allowed")    return ret_fn    def requires_premium_member(fn):    def ret_fn(*args,**kwargs):        lPermissions = get_permissions(current_user_id())        if 'premium_member' in lPermissions:            return fn(*args,**kwargs)        else:            raise Exception("Not allowed")    return ret_fn    @requires_admindef delete_user(iUserId):   """   delete the user with the given Id. This function is only accessable to users with administrator permissions   """@requires_logged_in def new_game():    """    any logged in user can start a new game    """    @requires_premium_memberdef premium_checkpoint():   """   save the game progress, only accessable to premium members   """```  Topic 4(主題4)-日誌(logging)-Python Standard LibraryPython 的 logging 可以將 log 輸出到 console 與輸出到日誌檔裡Python logging 的 log level 有五種等級，分別為DEBUG、INFO、WARNING、ERROR、CRITICAL，預設 log level 等級是 WARNING。log level 等級與分別對應的 api 如下：* DEBUG：logging.debug()* INFO：logging.info()* WARNING：logging.warning()* ERROR：logging.error()* CRITICAL：logging.critical()  Step 9: 基本 logging(預設 log level 等級是 WARNING)<jupyter_code>import logging

logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')<jupyter_output><empty_output><jupyter_text>Step 10: 基本 logging(將 log level 修改成 DEBUG)<jupyter_code>import logging

logging.basicConfig(level=logging.DEBUG)
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')<jupyter_output><empty_output><jupyter_text>Step 11: 進階 logging(設定 log 的 filename )<jupyter_code>import logging

log_filename = datetime.datetime.now().strftime("%Y-%m-%d_%H_%M_%S.log")
logging.basicConfig(level=logging.INFO, filename=log_filename, filemode='w',
	#format='[%(levelname).1s %(asctime)s] %(message)s',
	format='[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(message)s',
	datefmt='%Y%m%d %H:%M:%S',
	)

if __name__ == "__main__":
	logging.debug('debug')
	logging.info('info')
	logging.warning('warning')
	logging.error('error')
	logging.critical('critical')<jupyter_output><empty_output><jupyter_text>Step 12: 進階 logging(同時輸出到 console 與日誌檔 )<jupyter_code>import logging
import datetime

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter(
	'[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d] %(message)s',
	datefmt='%Y%m%d %H:%M:%S')

ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)

log_filename = datetime.datetime.now().strftime("%Y-%m-%d_%H_%M_%S.log")
fh = logging.FileHandler(log_filename)
fh.setLevel(logging.DEBUG)
fh.setFormatter(formatter)

logger.addHandler(ch)
logger.addHandler(fh)

if __name__ == "__main__":
	logging.debug('debug')
	logging.info('info')
	logging.warning('warning')
	logging.error('error')
	logging.critical('critical')<jupyter_output><empty_output><jupyter_text>Topic 5(主題5)-作業系統(os)-Python Standard Libraryhttps://docs.python.org/3/library/os.html提供了一種使用與操作系統相關的功能的便捷式途徑。* os.system()    括號中加入CMD指令，即可用Python執行(例如:os.system(ls))* os.walk()      遍歷資料夾或路徑* os.path()      主要用於獲取資料夾or檔案屬性或資訊* os.environ.get('PATH')    取得環境變數內容* os.rename(原檔名,新檔名)  更改文件檔名* os.remove(檔名)          刪除檔案* os.getcwd()              獲取當前目錄* os.mkdir(“資料夾名稱”)   建立資料夾* os.path.isdir(檔名)     檢查是不是目錄* os.path.expanduser('~')   取得家目錄路徑  Step 13: 判斷目錄是否存在，如果不存在就建立新目錄<jupyter_code>import os
import os.path

if not os.path.isdir("demo"):
    os.mkdir("demo")<jupyter_output><empty_output><jupyter_text>Step 14: 目前工作的目錄<jupyter_code>import os
     
# Get the current working directory (CWD)
cwd = os.getcwd()
     
# Print the current working directory (CWD)
print("Current working directory:", cwd)<jupyter_output><empty_output><jupyter_text>Step 15: 檢查目錄內的檔案是不是一個檔案，或檔案夾(子目錄)<jupyter_code>import os

path = 'sample_data'
print('Is "{}" a dictionary?'.format(path), os.path.isdir(path))

for fileName in os.listdir(path):
    print('Is "{}" a dictionary?'.format(fileName), os.path.isdir(path+'/'+fileName))<jupyter_output><empty_output><jupyter_text>Topic 6(主題6)-檔名匹配(glob)-Python Standard Libraryglob使用UNIX shell規則查找與一個模式匹配的文件名。只要程序需要查找文件系統中名字與某個模式匹配的一組文件，就可以使用這個模塊。  Step 16: 星號匹配<jupyter_code>import glob
for name in glob.glob('sample_data/*'):
  print(name)<jupyter_output><empty_output><jupyter_text>Step 17: 字元區間匹配<jupyter_code>import glob
for name in glob.glob('sample_data/[a-c]*'):
  print(name)<jupyter_output><empty_output><jupyter_text>Topic 7(主題7)-sys — 系統相關的參數以及函式  Step 18: sys.argv – command arguments<jupyter_code>import sys
if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('no argument')
        sys.exit()
    print(len(sys.argv))
    for arg in sys.argv:
      print(arg)<jupyter_output><empty_output><jupyter_text>Step 19: sys info functions* sys.platform 執行的平台* sys.version_info 當前 Python 的版本* sys.path Python 的執行路徑<jupyter_code>print(sys.platform)
print(sys.version_info)
print(sys.path)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13849394418114797, 'fraction_numerical': 0.010637177461822012, 'mean_word_length': 5.576177285318559, 'pattern_counts': {'":': 2, '<': 74, '<?xml version=': 0, '>': 73, 'https://': 4, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '268684', 'license': 'MIT', 'n_tokens_mistral': 4277, 'n_tokens_neox': 4415, 'n_words': 642, 'path': 'notebooks/AUP110_W15_Notebook.ipynb', 'repo_name': 'htchu/AUP110Course', 'size': '9495'}