簡明關鍵字參數/可變參數、對象的3種關係及文件的讀寫

關鍵字參數、可變參數

decorator - 裝飾器/包裝器

def say_hello(**kwargs):
    print(kwargs)
# 關鍵字參數        
    if 'name' in kwargs:
        print('你好,%s!' % kwargs['name'])
    elif 'age' in kwargs:
        age = kwargs['age']
        if age <= 16:
            print('你還是個小屁孩')
        else:
            print('你是一個成年人')
    else:
        print('請提供個人信息!')

# 可變參數
def my_sum(*args):
    total = 0
    for val in args:
        total += val
    return total

# 命名關鍵字參數
# 後面調用函數時*號後面的需要傳入關鍵字纔會生效
def foo(a, b, c, *, name, age):
    print(a + b + c)
    print(name,':', age)

def main():
    say_hello(name='念陽梟', age='23', qq='654321', gender=True)
    param = {'name':'劉闖','age':24,'tel':'12345678'}
    # 如果希望將一個字典作爲關鍵字參數傳入,需要在參數前放兩個*
    say_hello(**param)
    foo(1, 2, c=3, name='念', age=25)

def my_sum(my_list):
    total = 0
    for val in my_list:
        total += val
    return total

def my_mul(my_list):
    total = 1
    for val in my_list:
        total *= val
    return total

# 高階函數
# 通過向函數中傳入函數,可以寫出更通用的代碼
# calc函數中的第二個參數是另一個函,它代表了一個二元算法
# 這樣calc函數就不需要根某一種特定的二元運算耦合在一起
# 所以calc函數變得通用性更強,可以由傳入的第二個參數來決定到底做什麼運算
def calc(my_list,op):
    total = my_list[0]
    for index in range(1, len(my_list)):
        total = op(total, my_list[index])
    return total

def add(x, y):
    return x + y

def mul(x, y):
    return x * y

def main():
    mylist = [1,2,3,4,5]
    print(calc(mylist, add))
    print(calc(mylist, mul))

if __name__ == '__main__':
    main()

(屬性的)包裝器/裝飾器decorator

# 裝飾器語法
def record(fn):
    def wrapper(*args, **kwargs):
        print('準備執行%s函數...' % fn.__name__)
        # print(args)
        print(kwargs)

        # 此行代碼在執行被裝飾的函數
        # 在這行代碼的前後我們可以附加其他的代碼
        # 這些代碼可以讓我們在執行函數時做一些額外的工作
        val = fn(*args, **kwargs)
        print('%s函數執行完成' % fn.__name__)
        print('返回了%d' % val)
        # 返回被裝飾的函數的執行結果
        return val
    return wrapper

# 通過裝飾器修飾f函數,讓f函數在執行過程中可以做更多額外的操作
@record  # record記錄,履歷
def f(n):
    if n == 0 or n == 1:
        return 1
    return n * f(n-1)

if __name__ == '__main__':
    # fw = record(f)
    # print(fw(5))
    print(f(5))

類和類/對象和對象之間的三大關係

線段上有兩個點 - has-a - 關聯關係 整體不可分割的,叫做強關聯/聚合 eg:人有手,車有引擎

人使用了房子 - use-a - 使用,依賴關係

學生是人 - is-a - 繼承關係

# 繼承 - 從已經有的類創建新類的過程
# 提供繼承信息的稱爲父類(超類/基類)
# 得到繼承信息的稱爲子類(派生類/衍生類)
# 通過繼承我們可以將子類中的重複代碼抽取到父類中
# 子類通過繼承並複用這些代碼來減少重複代碼的編寫
# 將來如果要維護子類的公共代碼只需要在父類中進行操作即可

class Person(object):

    def __init__(self,name,age):
        self._name = name 
        self._age = age

    @property  # getter - 屬性訪問器
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

    @age.setter  # setter - 屬性修改器
    def age(self,age):
        self._age = age

    def watch_av(self):
        print('%s正在看片' % self._name)

class Student(Person):

    def __init__(self, name, age):
        super().__init__(name,age)  # 從父類Person繼承屬性name,age
        self._course = course

    @property
    def course(self):
        return self._course

    @course.setter
    def study(self,course):
        return '%s正在學習%s' % (self._name, course)

    # 方法重寫(override) - 覆蓋/置換/重寫  
    # 子類在繼承父類方法之後,對方法進行了重新實現
    # 當我們給子類對象發送watch_av消息時執行的是子類重寫過的方法
    def watch_av(self):
        print('學生正在跟蒼老師學習技術')

def main():
    stu1 = Student('李牧',40)
    stu2 = Student('鍾嶽',17)
    stu1.study('HTML網頁設計')
    stu2.watch_av()

if __name__ == '__main__':
    main()
  • Python沒有從語言層面支持抽象類的概念,我們可以通過abc模塊來製造抽象類的效果

    在定義類的時候通過指定metaclass=ABCMeta可以將類聲明爲抽象類

    抽象類是不能創建對象的,抽象類存在的意義是專門給其他類繼承

    abc模塊中還有一個包裝器abstractmethod,通過這個包裝器可以將方法包裝爲抽象方法,必須要求子類進行重寫

from abc import ABCMeta,abstramethod

class Employee(object,metaclass=ABCMeta):
    '''員工'''

    def __init__(self,name):
        '''初始化方法'''
        self._name = name

    @property
    def name(self):
        return self._name

    @abstractemethod
    def get_salary(self):
        '''獲得月薪...'''
        pass

class Manager(Employee):

    def get_salary(self):
        return 15000.00

class Programmer(Employee):

    def __init__(self,name):
        super().__init__(name)
        self._working_hour = 0

    @property
    def working_hour(self):
        return self._working_hour

    @working_hour.setter
    def working_hour(self,working_hour):
        self._working_hour = working_hour if working_hour > 0 else 0

    def get_salary(self):
        return 150.0 * self._working_hour

class Salesman(Employee):

    def __init__(self,name):
        super().__init__(name)
        self._sales = sales

    @property
    def sales(self):
        return self._sales

    @sales.setter
    def sales(self,sales):
        self._sales = sales if sales > 0 else 0

    def get_salary(self):
        return 1200.0 + self._sales * 0.05

def main():
    emps = [
        Manager('猴子'), Programmer('羅剎'),
        Manager('龍女'), Salesman('狐狸'),
        Salesman('牛魔'), Programmer('神將'),
        Programmer('和尚')
    ]
    for emp in emps:
        # isinstance判定一個對象是不是指定的類型
        if isinstance(emp, Programmer):
            emp.working_hour = int(input('請輸入%s本月工作時間:' % emp.name))
        elif isinstance(emp,Salesman):
            emp.sales = float(input('請輸入%s本月銷售額:' % emp.name))
        # 同樣是接收get_salary這個消息,但是不同的員工表現出了不同的行爲
        # 因爲三個子類都重寫了get_salary方法,所以這個方法會表現出多態行爲
        print('%s本月工資爲: ¥%.2f元' % (emp.name,emp.get_salary()))


if __name__ == '__main__':
    main()

讀取文件、寫文件

import time

def main():
    fs = open('hello.txt', 'r', encoding='utf-8')  # 把‘r’換成‘w’就是寫文件
    # 表示打開當前路徑下文件‘hello.txt’
    # content = fs.read()
    # print(content)

    # for line in fs:  # 一次讀一行
    #    print(line, end = '')
    #    time.sleep(0.5)
    mylist = fs.readlines()
    print(mylist)
    fs.close()

    # 寫文件
    # fs.write('彈木吉他抒情一些\n')
    # fs.write('可回憶騷動一整夜\n')
    # fs.write('寒冷卻下不了雪\n')

    # 用with讀取文件,如果在with下出現錯誤導致程序崩潰,就會退出,不會影響其他位置的程序
    # 輸入文件路徑也可以,.表示當前路徑,..表示上一級路徑
    with open('./abc/hello.txt', 'r', encoding='utf-8') as fs: 
        mylist = fs.readlines
        for line in mylist:
            print(line, end='')
            time.sleep(1)


if __name__ == '__main__':
    main()
  • 異常機制 - 處理程序在運行過程中出現的意外狀況的手段

    因爲不是所有的問題都能夠在寫程序調試程序的時候就能發現

import time

def main():
    try:  # 把要讀取的文件放到try裏面保護起來,讓文件即使讀取出現錯誤也能夠繼續執行後面的代碼
        with open('./abc/hello.txt', 'r', encoding='utf-8') as fs: 
            mylist = fs.readlines()
            for line in mylist:
                print(line, end='')
                time.sleep(1)
    except FileNotFoundError:  # 捕獲文件異常
        print('指定的文件無法打開.')  
    # except IOError:
    #     pring('讀寫文件時出現錯誤.')

    # except FileNotFoundError as e:
    #    print(e)             打印出現錯誤的文件
    #    print('指定的文件無法打開')
    print('程序執行結束.')


if __name__ == '__main__':
    main()
# 把1-100,101-1000,1001-10000的素數分別放入三個文件夾
from math import sqrt

def is_prime(n):
    assert n > 0  # 檢查n是否是有效數,無效則程序報異常不執行
    for factor in range(2, int(sqrt(n)) + 1):
        if n % factor == 0:
            return False
    return True if n != 1 else False

def main():
    filenames = ('a.txt', 'b.txt', 'c.txt')
    fs_list = []
    try:  # 我們也可以把可能出狀況(在執行時有風險)的代碼放到try代碼塊來執行
        for filename in filenames:
            fs_list.append(open(filename, 'w', encoding='utf-8'))
        for number in range(1, 10000):
            if is_prime(number):
                if number < 100:
                    fs_list[0].write(str(number) + '\n')
                elif number < 1000:
                    fs_list[1].write(str(number) + '\n')
                else:
                    fs_list[2].write(str(number) + '\n')

    except IOError:  # 如果try中出現了狀況就通過except來捕獲錯誤(異常)進行對應的處理
        print('讀寫文件發生錯誤')
    except FileNotFoundError:  # except可以寫多個分別用於處理不同的異常狀況
        pass
    # except BaseException:  處理所有的異常狀況
    #     pass

    # else:  如果沒有出狀況,那麼可以把無風險的代碼放到else中執行
    #     for number in range(1, 10000):
    #         if is_prime(number):
    #             if number < 100:
    #                fs_list[0].write(str(number) + '\n')
    #            elif number < 1000:
    #                 fs_list[1].write(str(number) + '\n')
    #             else:
    #                 fs_list[2].write(str(number) + '\n')
    finally:
        # 釋放文件資源,不管程序正常還是異常,最後這裏的代碼一定會執行,保證資源釋放
        # 所以此處是最好的釋放外部資源的位置,因爲這裏的代碼總是會執行
        for fs in fs_list:
            fs.close
    print('操作完成!')


if __name__ == '__main__':
    main()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章