python做業03-文件操做&函數

1、文件處理相關

一、編碼問題    python

  (1)請說明python2 與python3中的默認編碼是什麼?
答:Python2默認的字符編碼是ASCII,默認的文件編碼也是ASCII ;python3默認的字符編碼是unicode,默認的文件編碼是utf-8。web

    (2)爲何會出現中文亂碼?你能列舉出現亂碼的狀況有哪幾種?
答:不管以什麼編碼在內存裏顯示字符,在硬盤上存儲都是二進制。存到硬盤是以何種編碼,再從硬盤讀取出來,就必須是何種編碼,否則就會出現亂碼。解釋器默認編碼、Terminal編碼、文件編碼、操做系統語言設置。編程

    (3)如何進行編碼轉換?
答:對文件先decode爲unicode,再encode爲須要轉換的編碼。閉包

    (4)#-*-coding:utf-8-*- 的做用是什麼?
答:告訴解釋器這個文件的編碼格式是utf-8app

    (5)解釋py2 bytes vs py3 bytes的區別
答:python3把字符串的編碼改爲了unicode, 還把str和bytes作了明確區分, str就是unicode格式的字符,bytes是單純二進制。
    在python2裏,將string處理爲原生的bytes類型。

二、文件處理
    (1)r和rb的區別是什麼?
答:r是文本只讀模式
    rb:二進制只讀模式,沒法指定encoding,由於在該模式下數據讀到內存裏直接是bytes格式,如要查看內容還需手動decode
    (2)解釋一下如下三個參數的分別做用
     open(f_name,'r',encoding="utf-8")
答:f_name將打開的當前目錄文件名,r:文本只讀模式,encoding="utf-8":指定打開文件爲utf-8編碼模式。dom

2、函數基礎

一、寫函數,計算傳入數字參數的和。(動態傳參)ide

def func(*args):
    list1 = []
    sum_data = 0
    for i in args:
        list1.append(i)
        sum_data += i
    print(list1)
    print(sum_data)

func(313, 213, 12, 1234, 453, 56)

二、寫函數,用戶傳入修改的文件名,與要修改的內容,執行函數,完成整個文件的批量修改操做函數式編程

def file_modify(filename, old, new):
    import os
    f = open(filename, mode='r+', encoding='utf-8')
    new_f = open(filename+"_bak", mode='w', encoding='utf-8')
    for line in f:
        if old in line:
            line = line.replace(old,new)
        new_f.write(line)
    os.remove(filename)
    os.rename(filename+"_bak",filename)

file_modify('aaaa.txt', 'ddd', 'goodman')

三、寫函數,檢查用戶傳入的對象(字符串、列表、元組)的每個元素是否含有空內容。函數

def func(args):
    n = 0
    for i in args:
        if i == "":
            n += 1
    print("有%s個空內容"%n)

func((1, '', 2, 44, '', 12))

四、寫函數,檢查傳入字典的每個value的長度,若是大於2,那麼僅保留前兩個長度的內容,並將新內容返回給調用者。this

  dic = {"k1": "v1v1", "k2": [11,22,33,44]}
      PS:字典中的value只能是字符串或列表

def func(args_dic):
    for i in args_dic:
        if len(args_dic[i]) > 2:
            item = args_dic[i][0:2]  # 前兩項
            args_dic[i] = item
    print(args_dic)

dic = {"k1": "v1v1", "k2": [11,22,33,44]}
func(dic)
# {'k1': 'v1', 'k2': [11, 22]}

五、解釋閉包的概念
答:在一個外函數中定義了一個內函數,內函數裏運用了外函數的臨時變量,而且外函數的返回值是內函數的引用。這樣就構成了一個閉包。

3、函數進階

一、寫函數,返回一個撲克牌列表,裏面有52項,每一項是一個元組
    例如:[(‘紅心’,2),(‘草花’,2), …(‘黑桃A’)]

def poker():
    a = ['紅心', '草花', '方片', '黑桃']
    b = [2, 3, 4, 5, 6, 7, 8, 9, 10]
    c = ['J', 'Q', 'K', 'A']
    li = []
    for i in b:
        for j in a:
            item = (j,i)
            li.append(item)
    for m in c:
        for n in a:
            item2 = (n+m)
            li.append(item2)
    print(li)
    print(len(li))

poker()

二、寫函數,傳入n個數,返回字典{‘max’:最大值,’min’:最小值}
    例如:min_max(2,5,7,8,4)
    返回:{‘max’:8,’min’:2}

def min_max(*args):  # dict形式
    li = []
    for i in args:
        li.append(i)
    li.sort()
    dic = {'max':li[-1], 'min':li[0]}
    print(dic)

min_max(2,5,7,8,4)
# 輸出:{'max': 8, 'min': 2}

三、寫函數,專門計算圖形的面積
    其中嵌套函數,計算圓的面積,正方形的面積和長方形的面積
    調用函數area(‘圓形’,圓半徑) 返回圓的面積
    調用函數area(‘正方形’,邊長) 返回正方形的面積
    調用函數area(‘長方形’,長,寬) 返回長方形的面積

def area(type, *args):

    def rectangle(length, wide):
        return "長方形面積", length*wide

    def square(length):
        return "正方形面積", length**2

    def circlar(radius):
        import math
        return "圓形面積", math.pi*(radius**2)
    if type in locals():
        return eval(type)(*args)
print(area('rectangle', 133, 4))
print(area('circlar', 20))
print(area('square', 10))

四、寫函數,傳入一個參數n,返回n的階乘
    例如:cal(7)
    計算7*6*5*4*3*2*1

def cal(n):
    item = 1
    if int(n) == n:
        li = range(n+1)
        for i in li:
            if i == 0:
                pass
            else:
                item = item*i
        print(item)
    else:
        return "%s不是整數"%n

cal(3)

# 法二:
def cal(n):
    result=1
    for i in range(n, 0, -1): # 倒序
        result=result*i
    return result

print(cal(7))

五、編寫裝飾器,爲多個函數加上認證的功能(用戶的帳號密碼來源於文件),要求登陸成功一次,後續的函數都無需再輸入用戶名和密碼

user_db = {
    'hqs':'123',
    'susiff':'123',
    'guangfa':'123'
}

with open('db.txt', 'w', encoding='utf-8') as f:
    f.write(str(user_db))
login_db = {'user': None, 'status': False}
db_path = r'db.txt'

def login(func):
    def inner(*args,**kwargs):
        if login_db['user'] and login_db['status']:
            res = func(*args, **kwargs)
            return res
        user = input('input user:')
        passwd = input('input passwd:')
        with open(db_path, 'r', encoding='utf-8') as f:
            user_db2 = eval(f.read())
        if user in user_db2 and passwd == user_db2[user]:
            print('login ok')
            login_db['user'] = user
            login_db['status'] = True
            res = func(*args, **kwargs)
            return res
        else:
            print('login error')
    return inner  # 加括號執行,不加括號返回內存地址

@login
def home():
    print("首頁".center(40,'-'))

@login
def america(name):
    print("歐美專區".center(40,'-'))


home()
america('hqs')

4、生成器和迭代器

一、生成器和迭代器的區別?
能夠被next()函數調用並不斷返回下一個值的對象稱爲迭代器(Iterator).
在Python中,能夠在循環過程當中不斷推算後續元素,這種一邊循環一邊計算的機制,稱爲生成器(generator)。
生成器是迭代器的一種:
    1.生成器都是迭代器對象,但list\dict\str雖然是可迭代對象,但不是迭代器。
    2.把list\dict\str等可迭代對象變成迭代器可使用iter()函數

二、生成器有幾種方式獲取value?
  1.next():喚醒生成器並繼續執行
  2.send():喚醒生成器並繼續執行;發送一個信息到生成器內部。     3.for循環

三、經過生成器寫一個日誌調用方法, 支持如下功能

  • 根據指令向屏幕輸出日誌
  • 根據指令向文件輸出日誌
  • 根據指令同時向文件&屏幕輸出日誌
  • 以上日誌格式以下
2017-10-19 22:07:38 [1] test log db backup 3
2017-10-19 22:07:40 [2]    user alex login success 
#注意:其中[1],[2]是指自日誌方法第幾回調用,每調用一次輸出一條日誌
  •  代碼結構以下:
def logger(filename,channel='file'):
    """
    日誌方法
    :param filename: log filename
    :param channel: 輸出的目的地,屏幕(terminal),文件(file),屏幕+文件(both)
    :return:
    """
    ...your code...

 #調用
 log_obj = logger(filename="web.log",channel='both')
 log_obj.__next__()
 log_obj.send('user alex login success')

 解答以下:

def logger(filename, channel):
    """
    日誌方法
    :param filename: log filename
    :param channel: 輸出的目的地,屏幕(terminal),文件(file),屏幕+文件(both)
    :return:
    """
    import time
    a = time.localtime()
    log_time = time.strftime('%Y-%m-%d %H:%M:%S', a)
    count = 0
    while count < 10:
        count += 1
        sign = yield count
        log_info = log_time + ' [' + str(count) + '] ' + sign
        if channel == 'file':
            f = open(filename, mode='a+', encoding='utf-8')
            f.write('\n'+log_info)
            f.close()
        elif channel == 'terminal':
            print(log_info)
        elif channel == 'both':
            f = open(filename, mode='a+', encoding='utf-8')
            f.write('\n' + log_info)
            f.close()
            print(log_info)
        else:
            print('請輸入正確的模式!')


log_obj = logger(filename="web.log", channel='both')
log_obj.__next__()
log_obj.send('user alex login success')
log_obj.send('user hqs login success')

5、內置函數

一、用map來處理字符串列表,把列表中全部人都變成sb,比方alex_sb。

name = ['alex','wupeiqi','yuanhao','nezha']

print(list(map(lambda x: x+'_sb', name)))
"""
['alex_sb', 'wupeiqi_sb', 'yuanhao_sb', 'nezha_sb']
"""

二、用filter函數處理數字列表,將列表中全部的偶數篩選出來。

num = [1, 3, 5, 6, 7, 8]

print(list(filter(lambda x: x % 2 == 0, num)))
"""
[6, 8]
"""

三、以下,每一個小字典的name對應股票名字,shares對應多少股,price對應股票的價格。

portfolio = [
    {'name': 'IBM', 'shares': 100, 'price': 91.1},
    {'name': 'AAPL', 'shares': 50, 'price': 543.22},
    {'name': 'FB', 'shares': 200, 'price': 21.09},
    {'name': 'HPQ', 'shares': 35, 'price': 31.75},
    {'name': 'YHOO', 'shares': 45, 'price': 16.35},
    {'name': 'ACME', 'shares': 75, 'price': 115.65}
]

  計算購買每支股票的總價;用filter過濾出,單價大於100的股票有哪些?

portfolio = [
    {'name': 'IBM', 'shares': 100, 'price': 91.1},
    {'name': 'AAPL', 'shares': 50, 'price': 543.22},
    {'name': 'FB', 'shares': 200, 'price': 21.09},
    {'name': 'HPQ', 'shares': 35, 'price': 31.75},
    {'name': 'YHOO', 'shares': 45, 'price': 16.35},
    {'name': 'ACME', 'shares': 75, 'price': 115.65}
]


def sum_shares(dic):
    name = dic['name']
    shares = dic['shares']
    price = dic['price']
    sum_price = "%.2f" % (shares * price)
    new_dic = {'name':name, 'sum_price':sum_price}
    return new_dic


print(list(map(sum_shares, portfolio)))  # 每支總價
"""
[
  {'name': 'IBM', 'sum_price': 9110.00},
  {'name': 'AAPL', 'sum_price': 27161.00}, 
  {'name': 'FB', 'sum_price': 4218.00},
  {'name': 'HPQ', 'sum_price': 1111.25}, 
  {'name': 'YHOO', 'sum_price': 735.75}, 
  {'name': 'ACME', 'sum_price': 8673.75}]
"""

print(list(filter(lambda x: x['shares'] > 100, portfolio)))
"""
[{'name': 'FB', 'shares': 200, 'price': 21.09}]
"""

6、進階練習

一、請分別介紹文件操做中不一樣的打開方式之間的區別:

  r:文本只讀模式,以什麼模式存文件,就以什麼編碼打開文件

  rb:二進制只讀模式,該模式下數據讀取到內存裏直接就是bytes格式,沒法指定encoding

  r+:讀寫文件模式,可讀可寫可追加

  rb+:二進制讀寫模式,在內存中讀取寫入的均爲bytes格式

  w:只寫模式,不可讀,不存在則建立,存在則清空內容

  wb:二進制寫模式

  w+:寫讀模式,以建立的模式打開(將原文件覆蓋),能夠讀取寫入的內容

  wb+:二進制寫讀模式

  a:追加模式,可讀,不存在則建立,存在則只追加內容

  ab:二進制追加模式

  a+:同a

  ab+:同ab

二、有列表 li = ['alex', 'egon', 'smith', 'pizza', 'alen'], 請將以字母「a」開頭的元素的首字母改成大寫字母;

li = ['alex', 'egon', 'smith', 'pizza', 'alen']

def str_upper(x):
    if x[0] == 'a':
        x = 'A' + x[1:]
    else:
        pass
    return x

print(list(map(str_upper, li)))
"""
['Alex', 'egon', 'smith', 'pizza', 'Alen']
"""

三、有以下程序, 請給出兩次調用show_num函數的執行結果,並說明爲何:

num = 20

def show_num(x=num):
    print(x)

show_num()

num = 30

show_num()
"""
20
30
"""

答:函數參數x是取得num的值,num的值屬於全局變量,第一次調用函數的時候,全局變量num=20,第二次調用時,全局變量num發生了修改num=30

四、有列表 li = ['alex', 'egon', 'smith', 'pizza', 'alen'], 請以列表中每一個元素的第二個字母倒序排序;(後面調整解法)

li = ['alex', 'egon', 'smith', 'pizza', 'alen']


def str_sort(li):

    def cut_li(x):
        new_x = x[1:]
        return new_x
    new_li = list(map(cut_li, li))
    new_li.sort()
    new_li.reverse()
    final_li = []
    for i in new_li:
        for j in li:
            if i == j[1:]:
                final_li.append(j)

    print(final_li)


str_sort(li)

運用內置函數sorted改寫該題:

# 方法二:內置函數sorted()
li = ['alex', 'egon', 'smith', 'pizza', 'alen']
new_li = sorted(li, key=lambda x: x[1], reverse=True)
print(new_li)
"""
['smith', 'alex', 'alen', 'pizza', 'egon']
"""

五、有名爲poetry.txt的文件,其內容以下,請刪除第三行;

   昔人已乘黃鶴去,此地空餘黃鶴樓。

   黃鶴一去不復返,白雲千載空悠悠。

   晴川歷歷漢陽樹,芳草萋萋鸚鵡洲。

   日暮鄉關何處是?煙波江上令人愁。
import os
filename = 'poetry.txt'
file = open(filename, 'r', encoding='utf-8')
new_poetry = []
for line in file.readlines():
    if line.strip() == '':
        pass
    else:
        new_poetry.append(line.strip())
del new_poetry[2]
f = open('%s.new' % filename, 'w')
for i in new_poetry:
    f.write(i+'\n\n')
os.rename('%s.new' % filename, filename)

六、有名爲username.txt的文件,其內容格式以下,寫一個程序,判斷該文件中是否存在"alex", 若是沒有,則將字符串"alex"添加到該文件末尾,不然提示用戶該用戶已存在;

  pizza
  alex
  egon
filename = 'username.txt'
with open(filename, 'r+', encoding='utf-8') as f:
    name = 'alexx'
    i = f.read()
    print(i)
    if name in i:
        print('%s already in this %s' % (name, filename))
    else:
        f.write('\n'+name)

七、有名爲user_info.txt的文件,其內容格式以下,寫一個程序,刪除id爲100003的行;

  pizza,100001
  alex, 100002
  egon, 100003
import os
filename = 'user_info.txt'
with open(filename, 'r+', encoding='utf-8') as f:
    f_new = open('%s_new' % filename, 'w+', encoding='utf-8')
    for i in f:
        if '100003' in i:
            pass
        else:
            f_new.write(i)
# os.rename('%s_new' % filename, filename)  # 兩種都有效果
os.replace('%s_new' % filename, filename)

八、有名爲user_info.txt的文件,其內容格式以下,寫一個程序,將id爲100002的用戶修改成alex li

  pizza,100001
  alex, 100002
  egon, 100003
import os
filename = 'user_info.txt'
with open(filename,'r+', encoding='utf-8') as f:
    f_new = open('%s_new' % filename, 'w+')
    for i in f:
        if '100002' in i:
            line = i.split(',')
            line[0] = 'alex li'
            i = line[0] +', '+ line[1]
            f_new.write(i)
        else:
            f_new.write(i)
os.rename('%s_new' % filename, filename)

九、寫一個計算每一個程序執行時間的裝飾器;

import time
def timmer(func):

    def inner():
        start_time = time.time()
        func()
        wait_time = time.time() - start_time
        print("%s 運行時間:" % func.__name__, '%.2f' % wait_time)
    return inner


a = time.localtime()

@timmer
def log_1():
    print('%s-%s-%s'%(a.tm_year, a.tm_mon, a.tm_mday))
@timmer
def log_2():
    time.sleep(2)
    print('%s-%s-%s' % (a.tm_year, a.tm_mon, a.tm_mday))
@timmer
def log_3():
    time.sleep(4)
    print('%s-%s-%s' % (a.tm_year, a.tm_mon, a.tm_mday))
log_1()
log_2()
log_3()

十、lambda是什麼?請說說你曾在什麼場景下使用lambda?

答案:lambda函數就是能夠接受任意多個參數(包括可選參數)而且返回單個表達式值得函數

  優點:1.lambda函數比較輕便,即用即仍,適合完成只在一處使用的簡單功能。

     2.匿名函數,通常用來給filter,map這樣的函數式編程服務

     3.做爲回調函數,傳遞給某些應用,好比消息處理。

十一、題目:寫一個搖骰子游戲,要求用戶壓大小,賠率一賠一。

  要求:三個骰子,搖大小,每次打印搖骰子數。

import random
def dice(status):
    a = random.randint(1, 6)  # 返回1-6之間隨機數,包括6
    b = random.randint(1, 6)
    c = random.randint(1, 6)
    print(a, b, c)
    result = a + b + c
    if result > 10:
        print('結果是大!')
        if status == '':
            print('你贏了!!')
        if status == '':
            print('你輸了!!')
    else:
        print('結果是小!')
        if status == '':
            print('你贏了!!')
        if status == '':
            print('你輸了!!')

dice('')
相關文章
相關標籤/搜索