文章目录
00题. 微信未读信息数量提示
0. 问题描述及代码
将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果。
from PIL import Image, ImageDraw, ImageFont
def add_num_to_img(image_path, sign="2019"):
im = Image.open(image_path)
width, height = im.size
draw = ImageDraw.Draw(im)
#truetype是一种字体库,参数分别是字体,大小
font = ImageFont.truetype("arial.ttf", min(width//6, height//6))
draw.text((width*0.75, height*0.075), sign, font=font, fill=(255,33,33,255))
#rsplit分割,.左边是路径和文件名,.右边是文件格式
left, right = image_path.rsplit(".", 1)
new_iamge_path = left + "_" + sign + "." + right
im.save(new_iamge_path)
if __name__ == '__main__':
# for test
add_num_to_img("./sample.jpg")
print("Finished.")
1. split( ) , rsplit( ) , splitlines( )
语法:
s.split([sep=None][,count=S.count(sep)])
参数:
sep – 可选参数,指定的分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
count – 可选参数,分割次数,默认为分隔符在字符串中出现的总次数。
返回值:
返回分割后的字符串列表
实例:
#!/usr/bin/python3
S = "this is string example....wow!!!"
print (S.rsplit( ))
print (S.rsplit('i',1))
print (S.rsplit('w'))
['this', 'is', 'string', 'example....wow!!!']
['this is str', 'ng example....wow!!!']
['this is string example....', 'o', '!!!']
split( )从左向右寻找,rsplit( )相反。
splitlines( )根据换行符( \n )分割并将元素放入列表中。
c = "hello\nworld\ndlrb"
c1 = c.splitlines()
print(c1)
['hello', 'world', 'dlrb']
2. Pillow
PIL:Python Imaging Library,Python平台事实上的图像处理标准库。
PIL仅支持到python 2.7,Pillow 是其基础上的兼容版本,支持3.x
安装:
$ pip install pillow
操作图像:
ImageDraw画画,ImageFont字体,ImageFilter滤波处理(平滑、锐化、边界增强等)
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
# 随机字母:
def rndChar():
return chr(random.randint(65, 90))
# 随机颜色1:
def rndColor():
return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
# 随机颜色2:
def rndColor2():
return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
# 240 x 60:
width = 60 * 4
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype('Arial.ttf', 36)
# 创建Draw对象:
draw = ImageDraw.Draw(image)
# 填充每个像素:
for x in range(width):
for y in range(height):
draw.point((x, y), fill=rndColor())
# 输出文字:
for t in range(4):
draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
# 模糊:
image = image.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')
01题. 生成激活码
0. 问题描述及代码
作为 Apple Store App 独立开发者,你要搞限时促销,为你的应用生成激活码(或者优惠券),使用 Python 如何生成 20 个激活码(或者优惠券)?
import random, string
def rand_str(num, length=7):
f = open('01激活码.txt', 'w')
for i in range(num):
chars = string.ascii_letters + string.digits
s = [random.choice(chars) for i in range(length)]
f.write('{0}\n'.format(''.join(s)))
f.close()
print("Finished")
if __name__ == '__main__':
rand_str(20)
1. random模块
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import random
print( random.randint(1,10) ) # 产生 1 到 10 的一个整数型随机数
print( random.random() ) # 产生 0 到 1 之间的随机浮点数
print( random.uniform(1.1,5.4) ) # 产生 1.1 到 5.4 之间的随机浮点数,区间可以不是整数
print( random.choice('tomorrow') ) # 从序列中随机选取一个元素
print( random.randrange(1,100,2) ) # 生成从1到100的间隔为2的随机整数
a=[1,3,5,6,7] # 将序列a中的元素顺序打乱
random.shuffle(a)
print(a)
2. string模块ascii_letters和digits方法
ascii_letters生成所有字母(a-z&A-Z);digits生成所有数字(0-9)。
示例:
>>> chars = string.ascii_letters + string.digits
>>> print(chars)
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
3. 文件读写
写文件:
>>> f = open('/Users/michael/test.txt', 'w')
>>> f.write('Hello, world!')
>>> f.close()
这样更好:
with open('/Users/michael/test.txt', 'w') as f:
f.write('Hello, world!')
读文件同理:
with open('/path/to/file', 'r') as f:
print(f.read())
4. format 格式化函数
增强了字符串格式化的功能,基本语法是通过 {} 和 : 来代替以前的 %
>>>"{} {}".format("hello", "world") # 不设置指定位置,按默认顺序
'hello world'
02题. 保存激活码到 MySQL 关系型数据库
0. 问题描述及代码
将 0001 题生成的 20 个激活码(或者优惠券)保存到 MySQL 关系型数据库中。
import random
import pymysql
import string
def creat_num(num,length):
str = string.ascii_letters + string.digits
b = []
for i in range(num):
a = ''
for j in range(length):
a += random.choice(str)
b.append(a)
return b
def InsertIntoMysql(codelist):
# 打开数据库连接
db = pymysql.connect(host='127.0.0.1',user='root',passwd='919824467',db='mysql')
# 使用 cursor() 方法创建一个游标对象 cursor
cur = db.cursor()
#数据库语句
cur.execute('CREATE DATABASE IF NOT EXISTS code')
cur.execute('USE code')
cur.execute('''CREATE TABLE IF NOT EXISTS num(
id INT NOT NULL AUTO_INCREMENT,
code VARCHAR(32) NOT NULL,
PRIMARY KEY(id) )''')
for num in codelist:
cur.execute('INSERT INTO num(code) VALUES(%s)',(num))
cur.connection.commit()
db.close()
InsertIntoMysql(creat_num(200,10))
1. MySQL 教程
游标(cursor)是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果。每个游标区都有一个名字,用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理。
03题. 保存激活码到 Redis 非关系型数据库
0. 问题描述及代码
将 0001 题生成的 20 个激活码(或者优惠券)保存到 Redis 非关系型数据库中。
# -*- coding: utf-8 -*-
import redis
import random
import string
forSelect = string.ascii_letters + string.digits
def generate_code(count, length)
for x in range(count):
Re = ""
for y in range(length):
Re += random.choice(forSelect)
yield Re # generator 生成器
def save_code():
r = redis.Redis(host='127.0.0.1',port='6379',password='linyii')
codes = generate_code(20,7)
p = r.pipeline() # pipeline允许客户端一次发送多条命令
for code in codes:
# Redis Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。
p.sadd('code',code)
p.execute() # 执行
return r.scard('code') # Redis Scard 命令返回集合中元素的数量。
if __name__ == '__main__':
save_code()
1. yield函数 — generator(生成器)
在一个生成数列的函数中,使用 print(),而不用 return 会导致复用性差,因为函数返回 None,会使其他函数无法获得该函数生成的数列。
要提高该函数的可复用性,最好不要直接打印出数列,而是返回一个 List。
新的问题是,该函数在运行中占用的内存会随着 List 的增大而增大,如果要控制内存占用,最好不要用 List 来保存中间结果,而是通过 iterable 对象来迭代。
如果我们想要保持函数的简洁性,同时又要获得 iterable 的效果,yield 就派上用场了:
def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b
# print b
a, b = b, a + b
n = n + 1
仅仅把 print b 改为了 yield b,就在保持简洁性的同时获得了 iterable 的效果。
简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!
在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。
yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。
另一个 yield 的例子来源于文件读取。如果直接对文件对象调用 read() 方法,会导致不可预测的内存占用。好的方法是利用固定长度的缓冲区来不断读取文件内容。通过 yield,我们不再需要编写读文件的迭代类,就可以轻松实现文件读取:
def read_file(fpath):
BLOCK_SIZE = 1024
with open(fpath, 'rb') as f:
while True:
block = f.read(BLOCK_SIZE)
if block:
yield block
else:
return