### 第一模块内容
1. 请写出 “路飞学城alex” 分别用 utf-8 和 gbk 编码所占的位数(口述)
utf-8:一个中文字符占3个字节,英文字符占1个字节,则“路飞学城alex"一共16个字节,则共有16*8=128位。
gbk:一个中文占2个字节,英文字符占1个字节,则“路飞学城alex”一共12个字节,则共占12*8=96位
2. python有哪几种数据类型,分别什么?哪些数据类型是有序的。
基本类型有:数字(整数int、长整数long和浮点数float)、字符串(文本str和字节bytes)和布尔(True和False);
数据集有:列表list、元组tuple、字典dict和集合set。
有序的:字符串、列表、元组等
3. 列表和字典的pop方法有什么区别。
列表的pop()是删除最后一个;字典的pop()要制定k值的删除。
### 第一套题
1. 对文件"02第二模块之三体语录"进行增删改查 (文件操作编程)
''' 该语录视频没有讲解,我传到群文件了 直接发给学员 '''
1. 查,使用seek(15),和f.read(2)是什么字符,直接口述。
f = open('三体语录','r',encoding='utf-8')
f.seek(15) 打印出15,seek是找的字节;f.read(2)打印出1、,read读的是字符
2. 把第三行的“不要回答”替换成“绝对不能回复”
#方法一
import os f = open('三体语录','r',encoding='utf-8') f_new = open('三体语录.new','w',encoding='utf-8') for line in f: if '不要回答' in line: line = line.replace('不要回答','绝对不能回复') f_new.write(line) f.close() f_new.close() os.rename('三体语录.new','三体语录')
#方法二 f = open('三体语录','r+',encoding='utf-8') f1 = f.readline() f.seek(0) for line in f1: if '不要回答' in line: line_new = line.replace('不要回答','绝对不能回复') f.write(line_new) f.close()
3. 删掉最后一行
with open('三体语录','r',encoding='utf-8') as f: f1 = f.readlines() ##readline是读一行 和readlines是读出所有行的区别 with open('三体语录','w',encoding='utf-8')as f_w: for line in f1: if '25' in line: continue #跳出本次循环 f_w.write(line)
4. 解释一下替换过程发生了什么事情。
一种是在占硬盘的修改:以读的模式打开文件,再以写的模式打开一个新的文件;循环读文件,把要修改的替换掉;在新文件中写入每一行。
另外一种是在内存中修改:以读写的模式打开,先每一行的读出来,再把光标移到最开始,循环读到内存的,然后替换写入文件
5. 追加“给岁月以文明,而不是给文明以岁月”在第五行。(就是把其他的内容往下挤,不是覆盖第五行)
lines = [] f = open('三体语录','r',encoding='utf-8') for line in f: lines.append(line) lines.insert(5,'给岁月以文明,而不是给文明以岁月 ') s = ''.join(lines) with open('三体语录','w',encoding='utf-8')as f_write: f_write.write(s) f_write.close()
6. 最后一行替换成“给时光以生命,而不是给生命以时光”
lines = [] f = open('三体语录','r',encoding='utf-8') for line in f: lines.append(line) print(lines) lines[24] = '25、给时光以生命,而不是给生命以时光' s = ''.join(lines) with open('三体语录','w',encoding='utf-8')as f_write: f_write.write(s) f_write.close()
2. 编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
import time a = time.localtime() def logger(func): def inner(): with open('用户名和密码','r',encoding='utf-8') as f: lis = eval(f.read()) usename = input('请输入用户名:') passworld = input('请输入密码:') if usename == lis['_usename'] and passworld == lis['_passworld']: print('认证成功') func() else: print("您的输入有误") return inner @logger def log1(): print("%s-%s-%s"%(a.tm_year,a.tm_mon,a.tm_mday)) def log2(): time.sleep(2) print('%s-%s-%s' % (a.tm_year, a.tm_mon, a.tm_mday)) log1() log2()
3. 函数的参数 (口述)
- 形参和实参的区别。
形参变量:只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。
实参可以是常量、变量、表达式、函数等,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。
- 位置参数,默认参数,关键参数,非固定参数的顺序。
位置参数、关键参数、默认参数、非固定参数
- 解释下参数的作用。
参数可以让函数更灵活,还可以根据调用时传参的不同来决定函数内部的执行流程。
- 什么数据类型可以做实参。
常量、变量、表达式、函数等
4. 解释一下是否会报错,原因是什么?要是不报错打印什么值?报错的可以怎么改就不报错? (口述)
```
def test():
print(luffy)
luffy = "the king of sea."
```
不会报错,也不会打印,没有调用函数。
```
def test():
print(luffy)
luffy = 'e'
luffy = "the king of sea."
不会报错,也不会打印,因为没有调用函数。
```
```
def test():
luffy = 'e'
print(luffy)
luffy = "the king of sea."
```
不会报错不会打印,没有调用。
5. li = [1,2,3,5,5,6,7,8,9,9,8,3] 利用生成器功能,写一个所有数值乘以2的功能。(编程)
li = [1,2,3,5,5,6,7,8,9,9,8,3] a = [i*2 for i in li] print(a)
6. isinstance('s',str) 与 tupe('s') is str 效果是否一样?(口述)
效果一样
7. 序列化-json,xml,pickle (口述)
json和pickle的区别是什么?
json:只支持str、int、tuple、list、dict ;
pickle:支持python里的所有的数据类型;只能在python里使用。
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,通过<>节点来区别数据结构.
8. 描述写硬盘的编码转变(UTF-8格式,系统格式GBK) (口述)
系统文件先解码decode为Unicode,再编码encode为GBK的格式
9. 解释以下代码含义 (口述)
```
from functools import reduce
reduce(lambda x,y:x+y,range(10))
```
from functools import reduce reduce(lambda x,y:x+y,range(10)) print(reduce(lambda x,y:x+y,range(10)))
从functools库中导入reduce模块,reduce函数会对参数序列中元素进行累积。
reduce()函数返回一个值而不是一个list。首先需要定义一个需要对两个参数进行算数运算的函数。
reduce()函数首先会对list中的第一个value和第二个value进行这个算数运算,这会得到一个result。
之后它会对这个result和list中的第三个value进行这个算数运算得到一个新的result,最后得到最终的结果。
10. 打印日志11/26/2017 10:44:21 PM bug 24 并写入文件example.log中 (编程)
import logging logging.basicConfig(filename='example.log', level=logging.INFO,format='%(asctime)s %(message)s %(lineno)d', datefmt='%m/%d/%Y %I:%M:%S %p') # filemode=0o755, logging.warning("bug")
顺便告诉学员linux创建目录时候可以使用filemode=0o755 来指定权限
### 第二套
1. 编写带参数装饰器auth,
装饰器参数engine='file'时,模拟用户名username='luffy',密码password='city'认证
装饰器参数engine='mysql'时,模拟用户名username='alex',密码password='3714'认证
错误达到三次时退出程序
def auth(engine): def outer(func): def inner(*args,**kwargs): i = 0 while i < 3: username = input('Please input your username:') password = input('Please input your password:') if username == 'luffy' and password == 'city': print('欢迎luffy登录成功') res = func(*args,**kwargs) return res break elif username == 'alex' and password == '3714': print('欢迎alex登录成功!') resu = func(*args,**kwargs) return resu break else: print('您的输入有误,请重新输入:') i += 1 return inner return outer @auth(engine='file') def login1(): print('Login file successfully!') @auth(engine='mysql') def login2(): print('Login mysql successfully!') login1() login2()
2. 解释一下“w”和“wb”的区别(“r”和“rb”,“a”和“ab”) (口述)
f = open('三体语录', 'r' ,encoding='utf-8') mode=r表示只读模式
f = open('三体语录', 'rb' ) mode=rb 表示二进制模式
文件操作时,以 “a”或“ab” 模式打开,则只能追加,即:在原来内容的尾部追加内容
写入到硬盘上时,必须是某种编码的0101010,打开时需要注意:
ab,写入时需要直接传入以某种编码的0100101,即:字节类型;
a 和 encoding,写入时需要传入unicode字符串,内部会根据encoding制定的编码将unicode字符串转换为该编码的 010101010
f = open('三体语录', 'a' ,encoding='utf-8')
f = open('三体语录', 'ab' ,encoding='utf-8')
3. 描述写硬盘的编码转变(UTF-8格式,系统格式GBK) (口述)
系统文件先解码decode为Unicode,再编码encode为GBK的格式
4. 有两个磁盘文件A和B,各存放一行字母,要求把这两个文件中的信息合并(按字母顺序排列), 输出到一个新文件C中。(编程)
with open('test1','r',encoding='utf-8') as f1: a = f1.read() f1.close() f2 = open('test2','r',encoding='utf-8') b = f2.read() f2.close() f3 = open('tes3','w',encoding='utf-8') l = list(a + b) l.sort() s = '' s = s.join(l) f3.write(s) f3.close()
5. 装饰器的必备条件是什么?(口述)
装饰器本质为函数(用来装饰其他函数)添加附加功能
1不能修改被装饰函数的源代码;2不能修改函数的调用方式
高阶函数+嵌套函数 = 装饰器
6. 返回值 (口述)
- 默认的返回值是什么? None
- 返回值的个数限制? 没有
- 返回值的类型限制? 没有
7. 迭代器和生成器的区别, 在python中它们的原理是什么。(口述)
生成器:generator是指这种一边循环一边计算的机制;
迭代器:Iterator是指可以被next()函数调用并不断返回下一个值的对象。
迭代器与生成器的区别:
迭代器由Class对象创建. 生成器由包含yield表达的Function对象或者Generator Expression创建.
迭代器的原理:
(1)由Iterable.__iter__()返回Iterator.
(2)由Iterator.__next__()返回迭代值, 直到StopIteration.
一般迭代器同时实现__iter__()与__next__(), 在__iter__()返回self, 在__next__()返回迭代值,直到StopIteration
生成器原理:
(1)生成器都有next(), send(), close(), throw()
(2)调用next()/send(V)执行到下一个yield表达式,并返回yield表达式结果. 如果是send(V)将用V代替yield表达式的值往下执行, next()等价send(None)
(3)生成器不允许return任何值.
8. str,list,tuple,len 方法的作用及其它们的区别在哪里?
str()转成字符串,list()转成列表,tuple()转成元组,len()返回长度或个数
9. enumerate的作用是什么?(口述)
enumerate可以遍历索引又可以遍历元素;enumerate还可以接收第二个参数;用于指定索引起始值如下面例子enumerate(list1,1);
可以遍历字符串、列表、字典、数组等
list1 = [4,5,6,3,9,] for index, item in enumerate(list1): print(index, item)
10. 以下两次打印是否一致,一致请说明缘由,不一致请问如何修改使两次打印一致。 (口述)
```
import hashlib
m = hashlib.md5()
m.update(b'luffy')
m.update(b' city')
print(m.hexdigest())
m2 = hashlib.md5()
m2.update(b'luffycity')
print(m2.hexdigest())
```
重复调用update(arg)方法,是会将传入的arg参数进行拼接,而不是覆盖。
也就是说,m.update(a); m.update(b) 等价于m.update(a+b)
import hashlib m = hashlib.md5() m.update(b'luffy') m.update(b' city') print(m.hexdigest()) print(hashlib.md5(b'luffycity').hexdigest())
### 第三套
1. 字符串“Luffy”,将小写字母全部转换成大写字母,将大写字母转换成小写字幕,然后输出到一个磁盘文件"test"中保存。(编程)
s = 'Luffy' with open('test','w',encoding='utf-8') as f: f.write(s.swapcase())
2. 描述写硬盘的编码转变(UTF-8格式,系统格式GBK) (口述)
系统文件先解码decode为Unicode,再编码encode为GBK的格式
3. 作用域 (口述)
1. 什么是函数的作用域,举个例子说明一下。
限定这个名字的可用性的代码范围就是这个名字的作用域。
在python中一个函数就是一个作用域。无论在任何地方调用这个函数,永远回到它最开始的地方从上执行,往上找。
python中函数就是一个作用域,局部变量放置在其作用域中;代码完成后,作用域已经生成。
LEGB 代表名字查找顺序: locals ->enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间
globals 全局变量,函数定义所在模块的名字空间
builtins 内置模块的名字空间
a = 8 b = 10 def outer(): a = 0 b = 1 def inner(): a = 10 b = 11 inner() outer() print(a,b)
2. 以下代码最终结果是什么?
```
a = 8
b = 10
def outer():
a = 0
b = 1
def inner():
a = 10
b = 11
inner()
outer()
print(a,b)
```
打印出:8 10
```
# 考察内存空间
a = [1,2,3] def outer(): a.append(5) outer() print(a)
```
打印出:[1,2,3,5]
4. 迭代器带来的好处是什么 (口述)
使用迭代器不要求事先准备好整个迭代过程中的所有元素。
迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后元素可以不存在或者被销毁。
因此迭代器适合遍历一些数量巨大甚至无限的序列。
5. 写一个带参数的用户认证
def auth_argu(t): def auth(func): def wrapper(*args,**kwargs): user = input("请输入用户名:").strip() pas = input('请输入密码:').strip() if user == 'luffy' and pas == 'city': res = func(*args,**kwargs) return res return wrapper return auth @auth_argu(t = '传参') def log1(): print('登录成功') log1()
6. 装饰器的原理是什么, 请简要说一下一个函数加一个装饰器执行的流程.(口述)
装饰器decorator只是将函数作为参数的函数。通常,它的作用是返回封装好的经过修饰的函数.
装饰器在执行的时候,把函数test1当做参数传给了timer函数,timer函数执行结果就是返回了一个func的内存地址
执行函数test1的时候相当于是在调用deco
import time def timer(func): #timer(test1) | func=test1,把test1的内存地址传给了func;然后开始执行timer这个函数,只是声明了一个变量。 def deco(): ##timer(test1)函数的执行结果就只返回了一个deco的内存地址 start_time = time.time() func() #运行test1() stop_time = time.time() print('the func run time is %s'%(stop_time - start_time)) return deco @timer #--->> test1 = timer(test1) test1就相当于timer(test1) def test1(): time.sleep(2) print('in the test1') test1() ##test1执行相当于调用的是deco,执行的是deco这个函数
7. 利用sys模块和os模块 py/bin/start.py (口述)
```
[root@web01 py]# tree
.
├── bin
│ └── start.py
├── conf
│ └── account.ini
└── core
└── main.py
```
在start.py执行以下代码,请阐述一下代码含义。
```
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
```
BASE_DIR是绝对路径。sys.path.append(BASE_DIR) 把它加到环境变量里边
程序在哪执行,当前路径就是那个,要想导入其他模块就要找到它的路径。
8. 利用内置函数chr(),ord()以及random模块写一个简单随机4位验证码 (编程)
chr 把ascii码换成对应的符号,ord把符号换成ascii码
方法1:
import random checkcode = '' for i in range(4): current = random.randrange(0,4) if current != i: temp = chr(random.randint(65,90)) #chr把ascii码换成对应的符号 else: temp = random.randint(0,9) checkcode += str(temp) print(checkcode)
方法2::
import random,string source = string.digits + string.ascii_lowercase print("".join(random.sample(source,4)))
9. 写一个map函数 (编程)
a=map(lambda x:x+1 if x > 5 else x**2 ,[1,2,3,6,7,8]) for i in a: print(i)
10. 解释一下包和模块的含义。 (口述)
一个文件夹管理多个模块文件,这个文件夹就被称为包。 __init__ 把目录初始化成一个包。
在Python中,一个.py文件就称之为一个模块(Module)
### 第四套
1. 描述写硬盘的编码转变(UTF-8格式,系统格式GBK) (口述)
系统文件先解码decode为Unicode,再编码encode为GBK的格式
2. 编写sed功能,使用下面执行命令之后,“修改前的内容” 会被修改成 “修改后的内容”,该内容使用re模块进行匹配,不允许使用replace。 (编程)
```python
python3 sed.py 's#修改前的内容#修改后的内容#g' 修改文件名。
```
import sys,re msg = sys.argv[1] #sys.argv 命令行参数List,第一个元素是程序本身路径 filename = sys.argv[2] # msg = ' 's#修改前的内容#修改后的内容#g' old = re.search("'s#[^#]+#", msg).group()[3:-1] new = re.search("#[^#]+#g", msg).group()[1:-2] with open(filename,'r',encoding='utf-8')as f_read: with open(filename+".new","w",encoding='utf-8') as f_write: date_read = f_read.read() date_write = re.sub(old,new,date_read) f_write.write(date_write)
3. 简述内置函数globals() locals()的作用 (口述)
globals()获取当前代码里的所有全局变量;locals()获取当前代码里的所有局部变量
a = 12 b = 456 c = 789 d = globals() print(d) def f1(): a = 123 b = 456 c = 789 print(locals()) f1()
4. 利用内置函数 filter 和自定义函数获取l1大于33的所有元素 l1 = [11, 22, 33, 44, 55] (编程)
l1 = [11, 22, 33, 44, 55] for i in filter(lambda x:x>33,l1): print(i)
5. 编写3个函数,每个函数执行的时间是不一样的,
提示:可以使用time.sleep(2),让程序sleep 2s或更多。
import time def timer(func): #timer(test1) func=test1 def deco(): start_time = time.time() func() #运行test1() stop_time = time.time() print('the func run time is %s'%(stop_time - start_time)) return deco @timer def test1(): time.sleep(2) print('in the test1') @timer def test2(): time.sleep(3) print('in the test2') @timer def test3(): time.sleep(4) print('in the test3') #test1 = timer(test1) test1() #test2 = timer(test2) test2() test3()
6. 执行f.write()之后,会立刻写入磁盘吗?不会的话,有几种方式能让其写入磁盘中? (口述)
执行write方法之后,会写在内存当中,想写入磁盘有三种方案 (写入缓冲区,解决程序写入硬盘慢的问题)
1. f.flush(),打印实时日志使用
2. f.close()
3. 关闭程序
7. 函数闭包 (口述)
创建一个闭包函数需要满足哪几点:
必须有一个内嵌函数
内嵌函数必须引用外部函数中的变量
外部函数的返回值必须是内嵌函数
8. 写一个简单的加减乘除的函数。 (编程)
def calc(x,y): print(x+y) print(x-y) print(x*y) print(x//y) calc(9,3)
9. 利用hashlib模块和open函数写一个三次验证代码,要求如下:(编程)
1. 密码是加密的。
2. 三次登陆失败锁定账号在文件当中。
3. 登陆成功:使用一个全局变量进行记录
文件:正确用户信息 {'alex':'e99a18c428cb38d5f260853678922e03','kris':'202cb962ac59075b964b07152d234b70'}
锁定信息 []
i = 0 import hashlib file = open("正确用户信息",'r',encoding='utf-8') file_wrong = open("锁定信息",'r+',encoding='utf-8') line = eval(file.readline()) line_wrong = eval(file_wrong.readline()) name = input("请输入用户名:") passworld = input("请输入密码:") m = hashlib.md5() m.update(passworld.encode()) if name in line and name not in line_wrong: while i <= 3: if m.hexdigest() == line[name]: print('登录成功') break else: i +=1 print(' 您已经第%d次输错密码,输错3次账户将会被锁定'%(i)) if i < 3: passworld = input("请重新输入密码:") elif i == 3: print("已经输错3次,账户已被锁定") line_wrong.append(name) file_wrong.seek(0) file_wrong.write(str(line_wrong)) #file_wrong.tell() break elif name in line_wrong: print("该用户名已被锁定") else: print("该用户名不存在") exit()
10. time、datetime
将时间打印出成一个2017/10/01 18:08:15的格式
将 "2017-11-18" 17:43:43" 转换为 datetime的结构化时间
import time
print(time.strftime('%Y/%m/%d %H:%M:%S'))
import datetime d = datetime.datetime.now() print(d) print(d.day) print(datetime.datetime(2017,11,18,17,43,43))
### 未整理
1. 编写装饰器,为每个函数加上统计运行时间的功能
提示:在函数开始执行时加上start=time.time()就可纪录当前执行的时间戳,函数执行结束后在time.time() - start就可以拿到执行所用时间
见上
2. 编写装饰器,为函数加上认证的功能,即要求认证成功后才能执行函数
import time a = time.localtime() def logger(func): def inner(): _usename = 'kris' _passworld = 'abc123' usename = input('请输入用户名:') passworld = input('请输入密码:') if usename == _usename and passworld == _passworld: print('认证成功') func() else: print("您的输入有误") return inner def log1(): print("%s-%s-%s"%(a.tm_year,a.tm_mon,a.tm_mday))#13 @logger def log2(): time.sleep(2) print('%s-%s-%s' % (a.tm_year, a.tm_mon, a.tm_mday)) @logger def log3(): time.sleep(4) print('%s-%s-%s' % (a.tm_year, a.tm_mon, a.tm_mday)) log1() log2() log3()
3. read,readline,readlines的区别 (口述)
read([size])从文件当前位置起读取size个字节,若无参数size,则表示读取至文件结束为止。它的返回是字符串对象。
readline每次读取一行内容,所以读取时占用内存小,比较适合大文件。readline返回一个字符串对象。
readlines读取文件的所有行,保存在一个列表(list)变量中。每1个文件行作为一个list元素,但读取大文件会比较占内存。
4. 模拟登陆 (编程)
```
用户输入帐号密码进行登陆
用户信息保存在文件内
用户密码输入错误三次后锁定用户,下次再登录,检测到是这个用户也登录不了
```
见上
5. 从键盘输入一些字符,逐个把它们写到磁盘文件上,直到输入一个 # 为止。 (编程)
filename = input('输入文件名:') f = open(filename , "w+") ch = '' while '#' not in ch: f.write(ch) ch = input('输入字符串: ') f.close()
6. 函数的作用(特性/好处).(口述)
函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
特性:减少重复代码;使程序变的可扩展;使程序变得易维护。
7. 递归函数 (编程)
实现递归函数的条件有那些?
递归实现阶乘1*2*3*4*5*6*7 (获取最终阶乘的答案)
必须有一个明确的结束条件;每次进入更深一层递归时,问题规模相比上次递归都应有所减少
def calc(n): if n < 2: return 1 else: return n *calc(n-1) print(calc(7))
1. 快速找到26,不使用index等内置方法。二分法使用(编程)
[1,4,6,8,9,11,26,34,56,58,72,88]
data = [1,4,6,8,9,11,26,34,56,58,72,88] if len(data) >1: mid = int(len(data)/2) if data[mid] == 26: #find it print("找到数字",data[mid]) elif data[mid] > 26: print('我找的数在左边') ########################### data = [1,4,6,8,9,11,26,34,56,58,72,88] def binary_search(dataset,find_num): print(dataset) if len(dataset) >1: mid = int(len(dataset)/2) if dataset[mid] == find_num: #find it print("找到数字",dataset[mid]) elif dataset[mid] > find_num :# 找的数在mid左面 print("