点击蓝字
2023 1.16
JANUARY
关注我们
人间巧艺夺天工,炼药燃灯与昼同。
柳絮飞残铺地白,桃花落尽满街红。
纷纷灿烂如星陨,霍霍喧追似火烘。
后夜再翻花上锦,不愁零乱向东风。
——赵孟頫《赠放烟火者》
从古至今,每当新春来临时,人们总是燃放烟花,以表达对新年的祝福。兔年春节即将到来,源动随风带来Python代码,用现代的方式,绽放烟花,表达对新年的祝福。特别地,代码获取方式见文末。(可用PyCharm打开压缩文件夹中的firework.py文件)
#1
操作流程
兔年春节特刊(一)
1、进入 PyCharm官方下载页面(如下图所示),可以看到 PyCharm 有 2 个版本,分别是 Professional(专业版)和 Community(社区版)。其中,专业版是收费的,可以免费试用 30 天;而社区版是完全免费的。
建议初学者使用社区版,更重要的是,该版本不会对学习 Python 产生任何影响。
2、根据图上图所示点击“下载”按钮,等待下载完成。下载完成后,读者会得到一个 PyCharm 安装包(本节下载的是 pycharm-community-2019.2.2 版本)。双击打开下载的安装包,正式开始安装(如下图所示)。
3、安装完成后打开PyCharm社区版如下图所示
4、在PyCharm中打开firework.py文件
5、鼠标右键,点击Run'firework'
#2
代码分层简介
兔年春节特刊(一)
01
代码所用到的Python相关库函数
math库是python提供的内置数学类函数库,因为复数类型常用于科学计算,一般计算并不常用,因此math函数不支持复数类型,仅支持整数和浮点数运算。
random模块提供生成伪随机数的函数,在使用时需要导入random模块。 其中,random.random()最基本的随机函数,返回一个[0.0,1.0)之间的随机小数;random.uniform(a,b)是在指定范围内生成随机小数,两个参数其中一个是上限,一个是下限。如果a > b,则生成的随机数n: b <= n <= a;如果 a 。
threading模块创建线程的方式与 Java 类似,都是采用的类来创建线程。下面具体来讲讲threading相关函数。threading.active_count()用来返回正运行的线程数量(包括主线程),与len(threading.enumerate())结果相同;threading.current_thread()用来返回当前线程的变量;threading.main_thread()用来返回主线程;threading.enumerate()用来返回一个正在运行的线程的列表。
tkinter是python自带的GUI库,是对图形库TK的封装。同时,tkinter也是一个跨平台的GUI库,开发的程序可以在win,linux或者mac下运行。
re模块用来匹配字符串(动态、模糊的匹配),在网络爬虫中应用极为广泛。其中,match():从头匹配,search():从整个文本搜索,findall():找到所有符合的,split():分割,sub():替换,group():结果转化为内容,groupdict():结果转化为字典。
02
项目代码重点代码分析及相关基础知识
class
1、Python类的构造方法:class
python的class(类)相当于一个多个函数组成的家族,如果在这个Myclass大家族里有一个人叫f,假如这个f具有print天气的作用,那么如果有一天我需要这个f来print一下今天的天气,那么我必须叫他的全名MyClass.f才可以让他给我print,即在调用他的时候需要带上他的家族名称+他的名称。
下面是具体举例:
#Myclass家族,但是这个家族只有一个人f
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i) #家族x + 物品名i
print("MyClass 类的方法 f 输出为:", x.f()) #家族x + 人名f
输出结果:
MyClass 类的属性 i 为 :12345
MyClass 类的方法 f 输出 为 :hello world
2、类的构造方法__init__()
假如init()也是人,但是他是家族和外界联络员,当外界的人想调用自己家族的人,就必须要先告诉他,所以只要家族的人被调用,那么init()就会被先执行,然后由他去告诉那个被调用的人,执行被调用的。
下面是具体举例:
class Complex:
def __init__(self, realpart, imagpart): #必须要有一个self参数,
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
输出结果:
3.0 -4.5
3、类中方法的参数self
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数self, 且为第一个参数,self代表的是类的实例。
下面是具体举例:
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
#定义构造方法
def __init__(self,n,a):
self.name = n
self.age = a
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people('Python',10,30)
p.speak()
输出结果:
Python 说:我 10 岁。
Python中函数的用法
函数的定义以关键字def开头,后面接函数名称和圆括号。括号中放入函数需要的参数,通过冒号和缩进来控制函数内容。函数的结构体如下所示:
def 函数名(参数):
函数体
在学习一门语言时,我们最先学会的是如何输出Hello world。那么,我们的第一个函数也就从最简单的输出Hello world开始。
def hello():
print('Hello world!')
hello()
输出:
Hello world!
那么,什么是形参实参,什么是返回值呢?这里我们定义一个可以计算两个数之和的函数add1,可以先运行一下看看。
def add1(num1, num2):
result = num1 + num2
return result
x1, x2 = 1, 2
y = add1(x1, x2)
print(y)
输出:
3
if __name__ == ‘__main__‘
每个python模块(python文件,也就是此处的 test.py 和 import_test.py)都包含内置的变量 __name__,当该模块被直接执行的时候,__name__ 等于文件名(包含后缀 .py );如果该模块 import 到其他模块中,则该模块的 __name__ 等于模块名称(不包含后缀.py)。
而 “__main__” 始终指当前执行模块的名称(包含后缀.py)。进而当模块被直接执行时,__name__ == 'main' 结果为真。
#3
部分代码展示
兔年春节特刊(一)
import math, random,time
import threading
import tkinter as tk
import re
Fireworks=[]
maxFireworks=20
height,width=800,800
intervals=50
speed_fire=1
fire_num=20
status_num=intervals
class firework(object):
def __init__(self,color,speed,width,height):
self.radius=random.randint(2,4)
self.color=color
self.speed=speed
self.status=0
self.nParticle=random.randint(fire_num,fire_num)
self.center=[random.randint(0,height),random.randint(0,height)]
#self.center=[height/2,height/2]
self.oneParticle=[]
self.rotTheta=random.uniform(0,2*math.pi)
self.ellipsePara=[random.randint(width/8,height/4),random.randint(width/8,height/4)]
theta=2*math.pi/self.nParticle
for i in range(self.nParticle):
t=random.uniform(-1.0/16,1.0/16)
x,y=self.ellipsePara[0]*math.cos(theta*i+t), self.ellipsePara[1]*math.sin(theta*i+t)
xx,yy=x*math.cos(self.rotTheta)-y*math.sin(self.rotTheta), y*math.cos(self.rotTheta)+x*math.sin(self.rotTheta)
self.oneParticle.append([xx,yy])
self.curParticle=self.oneParticle[0:]
self.thread=threading.Thread(target=self.extend)
def extend(self):
for i in range(status_num):
self.status+=1
self.curParticle=[[one[0]*self.status/status_num, one[1]*self.status/status_num] for one in self.oneParticle]
time.sleep(self.speed/intervals)
def explode(self):
self.thread.setDaemon(True)
self.thread.start()
def __repr__(self):
return ('color:{color}\n'
'speed:{speed}\n'
'number of particle: {np}\n'
'center:[{cx} , {cy}]\n'
'ellipse:a={ea} , b={eb}\n'
'particle:\n{p}\n'
).format(color=self.color,speed=self.speed,np=self.nParticle,cx=self.center[0],cy=self.center[1],p=str(self.oneParticle),ea=self.ellipsePara[0],eb=self.ellipsePara[1])
def colorChange(fire):
rgb=re.findall(r'(.{2})',fire.color[1:])
return '#{0:0>2}{1:0>2}{2:0>2}'.format(rgb[0],rgb[1],rgb[2])
def appendFirework():
for i in range(1,maxFireworks):
cl='#{0:0>6}'.format(hex(int(random.randint(0,16777215)))[2:])
a=firework(cl,random.uniform(speed_fire,speed_fire),width,height)
Fireworks.append( {'particle':a,'points':[]} )
a.explode()
def show(cv):
if len(Fireworks)== 0:
appendFirework()
for p in Fireworks:
for pp in p['points']:
cv.delete(pp)
for p in Fireworks:
oneP=p['particle']
if oneP.status==status_num:
Fireworks.remove(p)
continue
else:
li=[[int(cp[0]*2)+oneP.center[0],int(cp[1]*2)+oneP.center[1]] for cp in oneP.curParticle]
color=colorChange(oneP)
for pp in li:
p['points'].append(cv.create_oval(pp[0]-oneP.radius, pp[1]-oneP.radius, pp[0]+oneP.radius, pp[1]+oneP.radius, fill=color))
root.after(intervals, show,cv)
if __name__=='__main__':
root = tk.Tk()
cv = tk.Canvas(root, height=height, width=width, bg = "black")
cv.pack()
root.after(intervals, show, cv)
root.mainloop()
#4
新春寄语
兔年春节特刊(一)
兔年即将到来,新春佳节,愿所有国人在这个特殊的春节,在这个奥密克戎肆虐的春节,在2023年的春节,能和家人团聚,家和万事兴。源动随风的粉丝们也可以用Python来绽放烟花,以表达对亲朋好友的祝福。
现在,用编程来解决问题早已深入各个行业之中,读者若有对Python语言的任何问题,都可在评论区留言。源动随风看到都会及时回复您,定将知无不言言无不尽。
另外,读者可关注本人的个人微信公众号:随风言天下,发送“烟花1”,获取本项目文件源代码。欢迎读者朋友们关注。(以下二维码即为微信公众号随风言天下对应二维码)。
图文编辑:源动随风
图文来源:源动随风 创客贴