函数编程

 

1. 编码问题

  i.请说明python2与python3中的默认编码是什么?

   python2 ASCII 码  python3 字符串为unicode,文件默认编码为utf-8

  ii.为什么会出现中文乱码?你能列举出现乱码的情况有哪几种?

  读取使用的编码和存储时使用的编码不一致造成的。

  存储的时候是GBK,打开的时候是使用UTF-8编码,就会出现乱码

  iii.如何进行编码转换?

h = "你好"
print(h)
print(type(h))
h1 = h.encode(encoding="utf-8")   #将字符串编码成utf-8的bytes
print(h1)
print(type(h1))
h2 = h1.decode(encoding="utf-8").encode(encoding="gbk")  
print(h2)
print(type(h2))
h3 = h2.decode(encoding="gbk") #将gbk编码的bytes解码成字符串(unicode)
print(h3)
print(type(h3))

你好
<class 'str'>
b'\xe4\xbd\xa0\xe5\xa5\xbd'
<class 'bytes'>
b'\xc4\xe3\xba\xc3'
<class 'bytes'>
你好
<class 'str'>

 

iv. #-*-coding:utf-8-*- 的作用是什么?

  使用utf-8编码。

v. 解释py2 bytes vs py3 bytes的区别:

  py2的 bytes和str 是一样的

  py3的bytes就是二进制字节

2. 文件处理

i. r 和 rb 的区别是什么?

  r 以只读的模式打开文件

  rb 以只读的二进制模式打开文件

ii. 解释一下以下三个参数的分别作用  

open(f_name,'r',encoding="utf-8")

  f_name 是文件名,r 为读的模式, encoding="utf-8" 为打开文件编码

 

函数基础:

1. 写函数,计算传入数字参数的和。(动态传参)
def num_sum(*args):
    total_sum = 0
    for i in args:
        total_sum += i
    print(total_sum)

num_sum(2,3,4,-1,12)

 

2. 写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整个文件的批量修改操作
import os
def updata(file,old_contents,new_contents):
    with open(file,"r",encoding="utf-8") as f ,open("tmp","w",encoding="utf-8") as f1:
        for line in f:
            line = line.replace(old_contents,new_contents)
            f1.write(line)
    os.remove(file)
    os.rename("tmp",file)

updata("file.txt","hello","hi")

 3. 写函数,检查用户传入的对象(字符串、列表、元组)的每一个元素是否含有空内容。

 

def isnull(arg):
    for i in arg:
        if str(i).isspace():
            print("有空白字符,空格 或 制表符 或 换行")

isnull(("hh","gg"," ","dd"))

 

4. 写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

def my_dic(*args,**kwargs):
    for i in kwargs:
        if len(kwargs[i]) > 2:
            print(len(kwargs[i]))
            kwargs[i] = kwargs[i][:2]
    return kwargs


dic = {"k1": "v1v1", "k2": [11,22,33,44]}
print(my_dic(**dic))

5. 解释闭包的概念。  

在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包,就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。

函数进阶:

1. 写函数,返回一个扑克牌列表,里面有52项,每一项是一个元组
例如:[(‘红心’,2),(‘草花’,2), …(‘黑桃A’)]

def poker():
    type_list = ("黑桃","红桃","方块","梅花")
    num_list = (1,2,3,4,5,6,7,8,9,10,"J","Q","K")
    poker_list = []
    for i in type_list:
        for j in num_list:
            poker_list.append((i,j))
    print(poker_list)
poker()

  

2. 写函数,传入n个数,返回字典{‘max’:最大值,’min’:最小值}

例如:min_max(2,5,7,8,4)
返回:{‘max’:8,’min’:2}


def min_max(*args):
    max = args[0]
    min = args[0]
    for i in args:
        if i >max:
            max = i
        if i< min:
            min = i
    return {"max":max, "min":min}

print(min_max(100,-6,2,3,6,98))

  

3. 写函数,专门计算图形的面积

其中嵌套函数,计算圆的面积,正方形的面积和长方形的面积
调用函数area(‘圆形’,圆半径) 返回圆的面积
调用函数area(‘正方形’,边长) 返回正方形的面积
调用函数area(‘长方形’,长,宽) 返回长方形的面积
def area():
    def 计算长方形面积():
        pass

    def 计算正方形面积():
        pass

    def 计算圆形面积():
        pass


def area(shape,*args):
    def rectangular(*args):
        area_total = args[0]*args[1]
        print(area_total)

    def square(*args):
        area_total = args[0] * args[0]
        print(area_total)
    def circular(*args):
        area_total =  3.14* args[0] * args[0]
        print(area_total)

    if shape == "长方形":
        return rectangular(*args)
    elif shape == "正方形":
        return square(*args)
    elif shape == "圆形":
        return circular(*args)

area("圆形",2)

 

4. 写函数,传入一个参数n,返回n的阶乘

例如:cal(7)
计算7*6*5*4*3*2*1

def cal(n):
    total = 1
    for i in range(1,n+1):
        total *= i
    print(total)
    
cal(7)

  

5. 编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码


import json

logged = False
global_user = ""
def auth(fun):
    def inner(*args,**kwargs):
        global logged
        if logged == False:
            user = {
                "zhangsan": ["zhangsan666",3,False],
                "lisi": ["lisi666",0,True],
                "wangwu": ["wangwu666",0,True]
            }    #用户名:[密码,密码输错次数,False锁定用户]
            while True:
                name = input("请输入你的姓名:").strip()
                try:
                    with open("lockedname.txt","r+",encoding="utf-8") as f:
                        user = json.load(f)  #若是有lockedname.txt文件,则user重新赋值
                    with open("expenses_record.txt", "r+", encoding="utf-8") as f2:
                        record_info = json.load(f2)  # 若是有lockedname.txt文件,则user重新赋值
                except Exception as err:
                    pass
                if name not in user:
                    print("用户名不存在,请重新输入")
                    continue
                elif user[name][2] == False:
                    print("用户已经被锁定,请联系管理员")
                    continue
                elif record_info[name]["frozen"] == True:
                    print("账号已经被冻结,请联系管理员")
                    continue
                elif name in user:
                    passwd = input("请输入你的密码:").strip()
                    if passwd == user[name][0]:  # 判断用户名密码
                        print("欢迎 %s 同学"%(name))
                        user[name][1] = 0
                        with open("lockedname.txt", "w", encoding="utf-8") as f:
                            json.dump(user, f)
                        logged = True
                        global global_user
                        global_user = name
                        result = fun(*args,**kwargs)
                        return (0, name)
                    else:
                        user[name][1] += 1  # 同一个用户名输错密码加一
                        print("密码错误")
                        if user[name][1] >= 3:
                            print("用户账号已被锁定")
                            user[name][2] = False
                        with open("lockedname.txt", "w", encoding="utf-8") as f:
                            json.dump(user, f)
        else:
            result = fun(*args, **kwargs)
    return inner

@auth
def tixian(name, cash_amount):
    pass

@auth
def zhuanzhuang():
    pass

  

生成器和迭代器

1. 生成器和迭代器的区别?

  生成器是迭代器的一种,能做所有迭代器的事,而且因为自动创建了 iter()和 next()方法,生成器简洁,高效。使用生成器节省内存。

2. 生成器有几种方式获取value?

  next()

  for 循环

3. 通过生成器写一个日志调用方法,支持以下功能

根据指令向屏幕输出日志

根据指令向文件输出日志

根据指令同时向文件&屏幕输出日志

日志格式如下

2017-10-19 22:07:38 [1] test log db backup 3
2017-10-19 22:07:40 [2] user alex login success

代码结构如下

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')

 

import logging

def logger(filename,channel='terminal'):
    """
    日志方法
    :param filename: log filename
    :param channel: 输出目的地,屏幕(҅terminal),文件(file),屏幕+文件(both)
    :return:
    """
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    fh = logging.FileHandler(filename, encoding="utf-8")
    fh.setLevel(logging.DEBUG)
    formatter = logging.Formatter(
        fmt="%(asctime)s %(message)s",
        datefmt="%Y/%m/%d %X",
      )
    ch.setFormatter(formatter)
    fh.setFormatter(formatter)
    count = 0
    while True:
        count += 1
        mg = yield "ok"+str(count)
        # mg = yield
        meg = "[%s] %s"%(count,mg)
        if channel == 'terminal':
                log.addHandler(ch)
                log.info(meg)
                log.removeHandler(ch)
        elif channel == 'file':
                log.addHandler(fh)
                log.info(meg)
                log.removeHandler(fh)
        elif channel == 'both':
                log.addHandler(ch)
                log.addHandler(fh)
                log.info(meg)
                log.removeHandler(ch)
                log.removeHandler(fh)

ll = logger("text.log",channel='both')
print(ll.__next__())
print(ll.send('user alex login success'))
ll.send('user lili login success')
ll.send('user nana login success')

  

内置函数

 1,用map来处理字符串列表,把列表中所有人都变成sb,比方alex_sb

 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。

 

def f(arg):
    arg = arg+"_sh"
    return arg
lis = ["alex","lili","wangwu"]
lis_new = map(f,lis)
print(lis_new.__next__())
print(lis_new.__next__())
print(lis_new.__next__())


2,用filter函数处理数字列表,将列表中所有的偶数筛选出来

 

filter()用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。

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

def f1(n):
    if n%2 == 0:
        return True
    else:
        return False
num = [1,3,5,6,7,8]
num_new = filter(f1,num)

print(num_new.__next__())
print(num_new.__next__())


num_new2 = filter(lambda x:x%2 == 0,[1,3,5,6,7,8])
print(num_new2.__next__())
print(num_new2.__next__())



3,如下,每个小字典的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}
]

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 f2(i):
    if i['price'] > 100:
        return True
portfolio_new = filter(f2,portfolio)

# print(portfolio_new.__next__())
# print(portfolio_new.__next__())

for i in portfolio_new:
    print(i)

  



posted @ 2019-03-19 16:49  沙中石~  阅读(237)  评论(0编辑  收藏  举报