Python中的三种编程方式(编程思想)
Python
编程有面向过程、面向函数、面向对象三种方式:
- 面向过程:根据业务逻辑从上到下写代码
import requests # 导入一些模块
import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
# 邮件设置
from_addr = "发件QQ邮箱地址"
password = "qq邮箱授权码"
to_addr = "任意收件邮箱地址"
smtp_server = "smtp.qq.com"
port = 587
while True:
# 获取最近价格
symbol = "BTCUSDT"
response = requests.get("https://api.binance.com/api/v3/ticker/price?symbol=%s" % (symbol)).json()
price = float(response['last'])
if price > 20000:
data = "当前价格已达到2万美元!"
msg = MIMEText(data, 'plain', 'utf-8') # 发送内容
name, addr = parseaddr('Alert <%s>' % from_addr)
msg['From'] = formataddr((Header(name, 'utf-8').encode(), addr))
name, addr = parseaddr('交易者 <%s>' % to_addr)
msg['To'] = formataddr((Header(name, 'utf-8').encode(), addr))
msg['Subject'] = Header('交易提醒', 'utf-8').encode()
server = smtplib.SMTP(smtp_server, port) # 连接邮箱服务器
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string()) # 发送邮件
server.quit() # 关闭连接
elif price > 15000:
data = "当前价格已达到1.5万美元!"
msg = MIMEText(data, 'plain', 'utf-8') # 发送内容
name, addr = parseaddr('Alert <%s>' % from_addr)
msg['From'] = formataddr((Header(name, 'utf-8').encode(), addr))
name, addr = parseaddr('交易者 <%s>' % to_addr)
msg['To'] = formataddr((Header(name, 'utf-8').encode(), addr))
msg['Subject'] = Header('交易提醒', 'utf-8').encode()
server = smtplib.SMTP(smtp_server, port) # 连接邮箱服务器
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string()) # 发送邮件
server.quit() # 关闭连接
elif price > 12000:
data = "当前价格已达到1.2万美元!"
msg = MIMEText(data, 'plain', 'utf-8') # 发送内容
name, addr = parseaddr('Alert <%s>' % from_addr)
msg['From'] = formataddr((Header(name, 'utf-8').encode(), addr))
name, addr = parseaddr('交易者 <%s>' % to_addr)
msg['To'] = formataddr((Header(name, 'utf-8').encode(), addr))
msg['Subject'] = Header('交易提醒', 'utf-8').encode()
server = smtplib.SMTP(smtp_server, port) # 连接邮箱服务器
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string()) # 发送邮件
server.quit() # 关闭连接
面向过程编程虽然容易学习上手,但其往往需要一长段代码来实现指定功能,开发过程中最常见的操作就是复制粘贴,即:将之前实现的代码块复制到现需功能处,代码冗长,效率低下。
- 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
import requests # 导入一些模块
import smtplib
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
def get_latest_price(symbol):
"""
获取币安交易所指定交易对的最新价格
:param symbol: 交易对名称,例如"BTCUSDT"
:return: 最新价格,浮点数类型
"""
response = requests.get("https://api.binance.com/api/v3/ticker/price?symbol=%s" % (symbol)).json()
price = float(response['last'])
return price
def send_mail(data):
"""
发送邮件
:param data: 要发送的邮件内容
:return:
"""
from_addr = "发件QQ邮箱地址"
password = "qq邮箱授权码"
to_addr = "任意收件邮箱地址"
smtp_server = "smtp.qq.com"
port = 587
msg = MIMEText(data, 'plain', 'utf-8') # 发送内容
name, addr = parseaddr('Alert <%s>' % from_addr)
msg['From'] = formataddr((Header(name, 'utf-8').encode(), addr))
name, addr = parseaddr('交易者 <%s>' % to_addr)
msg['To'] = formataddr((Header(name, 'utf-8').encode(), addr))
msg['Subject'] = Header('交易提醒', 'utf-8').encode()
server = smtplib.SMTP(smtp_server, port) # 连接邮箱服务器
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string()) # 发送邮件
server.quit() # 关闭连接w2
while True:
price = get_latest_price("BTCUSDT")
if price > 20000:
send_mail("当前价格已达到2万美元!")
elif price > 15000:
send_mail("当前价格已达到1.5万美元!")
elif price > 15000:
send_mail("当前价格已达到1.5万美元!")
- 面向对象:函数式编程对于开发小型项目非常有用,但是一旦项目变大,仅仅使用函数式编程就可能变得混乱,因此我们需要进一步地组织和简化我们的代码,这时候我们就需要使用到面向对象编程了。
面向对象编程
Python
语言在设计之初就被设计为面向对象的程序设计语言,面向对象这一编程方式的实现是通过使用类
和对象
,因此类
和对象
是面向对象
的核心。
面向对象的业务场景
假设我们现在正在开发一款手游,王者荣耀
大家或许都听说过或者玩过吧?那么我们就来尝试着进行模拟的开发。
我们知道王者荣耀
是腾讯天美工作室推出的英雄竞技手游,游戏中有很多的英雄,而每个英雄都有各自的属性,也可以使用不同的技能,假设我们现在要去编写代码,使得玩家可以在游戏中查看不同英雄各自的属性以及使用技能。
我们先来使用函数式编程的方式:
# 查看公孙离的属性和使用技能
def view_gongsunli_attributes():
profession = "射手"
speciality = "突进/收割"
difficulty = "★★★★★★★"
print("【公孙离的属性】职业是:{} 特长是:{} 上手难度:{}".format(profession, speciality, difficulty))
def use_gongsunli_skill1():
print("阿离向指定方向瞬步")
def use_gongsunli_skill2():
print("阿离旋转起舞操控纸伞飞旋,击落飞行物并对范围内敌人造成两端打击")
def use_gongsunli_skill3():
print("阿离击退前方的敌人,并将纸伞向指定方向掷出")
# 查看王昭君的属性和使用技能
def view_wangzhaojun_attributes():
profession = "法师"
speciality = "控制/冰冻"
difficulty = "★★★★"
print("【王昭君的属性】职业是:{} 特长是:{} 上手难度:{}".format(profession, speciality, difficulty))
def use_wangzhaojun_skill1():
print("王昭君操控碎裂冰晶绽开,对范围内的敌军造成法术伤害与冰冷效果")
def use_wangzhaojun_skill2():
print("王昭君在指定区域释放寒霜之力,短暂延迟后对指定区域造成伤害和2.5秒冰冻效果")
def use_wangzhaojun_skill3():
print("王昭君召唤寒冬之力,在指定位置降下风雪对范围内敌人造成法术伤害与冰冷效果")
我们现在已经写好了两个英雄公孙离
与王昭君
的代码,我们现在就来自编自导,当一回游戏玩家:
view_gongsunli_attributes() # 查看公孙离的英雄属性
use_gongsunli_skill1() # 使用公孙离的一技能
use_gongsunli_skill2() # 使用公孙离的二技能
use_gongsunli_skill3() # 使用公孙离的三技能
view_wangzhaojun_attributes() # 查看王昭君的英雄属性
use_wangzhaojun_skill1() # 使用王昭君的一技能
use_wangzhaojun_skill2() # 使用王昭君的二技能
use_wangzhaojun_skill3() # 使用王昭君的三技能
游戏体验还不错!
但是问题来了,我们目前还仅仅是完成了两个英雄角色的创建,而游戏中英雄角色众多,如果要复制粘贴,再修改其中信息,也是要花费大量时间精力的吧?而且玩家在查看英雄属性或者使用技能时并不方便,每次查看英雄属性或者使用英雄技能都要使用包含不同英雄名称的函数,这就造成我们游戏的开发以及玩家的游戏体验都不好,有没有什么办法既可以大大简化游戏开发(此处是英雄角色创建),又可以大大提高玩家的游戏体验呢?
当然有,那么我们就来使用面向对象编程的方式完成对于英雄角色的创建这一工作,看看是否能使用更简单的方式完成这一纷繁复杂的工作。
class Hero: # 创建一个英雄类
def __init__(self, name, profession, speciality, difficulty, skill1, skill2, skill3):
"""英雄的一些属性"""
self.name = name
self.profession = profession
self.speciality = speciality
self.difficulty = difficulty
self.skill1 = skill1
self.skill2 = skill2
self.skill3 = skill3
def view_attributes(self):
"""查看英雄属性"""
print("【{}的属性】职业是:{} 特长是:{} 上手难度:{}".format(self.name, self.profession, self.speciality, self.difficulty))
def use_skill1(self):
"""使用技能一"""
print(self.skill1)
def use_skill2(self):
"""使用技能二"""
print(self.skill2)
def use_skill3(self):
"""使用技能三"""
print(self.skill3)
# 创建好一个模板之后,我们就可以很方便地创建具体的英雄角色了
gongsunli = Hero(
name="公孙离",
profession="射手",
speciality="突进/收割",
difficulty="★★★★★★★",
skill1="阿离向指定方向瞬步",
skill2="阿离旋转起舞操控纸伞飞旋,击落飞行物并对范围内敌人造成两端打击",
skill3="阿离击退前方的敌人,并将纸伞向指定方向掷出"
)
wangzhaojun = Hero(
name="王昭君",
profession="法师",
speciality="控制/冰冻",
difficulty="★★★★",
skill1="王昭君操控碎裂冰晶绽开,对范围内的敌军造成法术伤害与冰冷效果",
skill2="王昭君在指定区域释放寒霜之力,短暂延迟后对指定区域造成伤害和2.5秒冰冻效果",
skill3="王昭君召唤寒冬之力,在指定位置降下风雪对范围内敌人造成法术伤害与冰冷效果"
)
# 要完成更多英雄角色的创建,我们只需要使用这样的方式就可以了,此处我们省略,现在开始切换到玩家角色
wangzhaojun.view_attributes() # 查看王昭君的属性
wangzhaojun.use_skill1() # 使用王昭君的一技能
wangzhaojun.use_skill2() # 使用王昭君的二技能
wangzhaojun.use_skill3() # 使用王昭君的三技能
gongsunli.view_attributes() # 查看公孙离的属性
gongsunli.use_skill1() # 使用公孙离的一技能
gongsunli.use_skill2() # 使用公孙离的二技能
gongsunli.use_skill3() # 使用公孙离的三技能
# 我们作为玩家,也明显可以体验到,现在无论是查看英雄的属性或者使用英雄的技能都更加方便了,游戏体验大大提高!
面向对象编程的优点
- 将具有相同属性和方法的一类对象(在我们的案例中,不同英雄角色虽然各自具体的属性以及技能不同,但本质上是相同的)抽象为一个类,分别封装它们的属性和可以调用的方法(在我们的案例中使用英雄技能就是调用方法),方便了数据的管理与方法的调用,尤其是在开发大型项目时更有帮助。
- “面向对象”相较于“面向过程”,带给我们的是“认识和抽象世界的一种更有效的思路”。更接近自然世界的描述方式,容易理解。
-
增强了项目的可维护性和可扩展性。
试想如果我们是
王者荣耀
的程序开发人员,现在我们要对我们的项目进行后续维护,使用面向对象的编程方式更易于维护。1.创建一个新英雄李白,我们就不需要再去重复写函数了,只需要直接向模板中填入信息即可创建:
libai = Hero( name="李白", profession="刺客", speciality="突进/收割", difficulty="★★★★", skill1="李白向指定方向突进两次,第三次释放回到原地", skill2="李白原地释放剑阵,期间不可被选中,对范围内敌人造成伤害和破甲效果", skill3="李白化身剑气,对指定范围造成五次飞剑伤害,期间不可选中" )
2.英雄重做或更新英雄信息:
gongsunli = Hero( name="公孙离", profession="射手", speciality="突进/收割", difficulty="★★★★★", # 修改上手难度信息 skill1="阿离向指定方向瞬步", skill2="阿离旋转起舞操控纸伞飞旋,击落飞行物并对范围内敌人造成三段打击", # 改成三段打击 skill3="阿离击退前方的敌人,并将纸伞向指定方向掷出" )
3.为了提高玩法的丰富性,所有英雄由原来的三个可用技能变为四个,也就是所有英雄增加一个技能:
def __init__(self, name, profession, speciality, difficulty, skill1, skill2, skill3, skill4): """英雄的一些属性""" self.name = name self.profession = profession self.speciality = speciality self.difficulty = difficulty self.skill1 = skill1 self.skill2 = skill2 self.skill3 = skill3 self.skill4 = skill4 # 增加一个属性,也就是对于新增技能的技能描述 def use_skill4(self): # 增加一个方法 """使用技能四""" print(self.skill4) # 我们不需要一个个去进行修改,只需要简单地修改一下我们的模板 # 变量和属性本是一个东西,方法和函数是一个东西。但是区别是:变量是自由的,属性是属于某个对象的。函数是自由的,方法是属于某个对象的。
-
对于大型项目,可以更好地进行架构设计,而不至于项目混乱。
还是以
王者荣耀
这款游戏为例,除了英雄角色创建这一工作以外,游戏中还有铭文
、商城
、好友管理
等等功能,为每一个类型的项目单独设计一个类来统一简化我们的工作,可以使项目架构更为清晰,而且各个功能之间耦合性弱,实现了高内聚低耦合
,使程序模块的可重用性、移植性大大增强。
类和对象
什么是类和对象?
类是对具有相同属性和行为的一类对象的抽象。可以把类看作为一个模板或者设计图纸,通过这个模板、设计图纸可以创建众多具有相似特征和共同行为的对象。
对象是类实例化后的实体。
例如:汽车产商在生产汽车时,肯定是要先由研发部门进行设计,设计出来的汽车模型就是一个类,而生产部门根据这个模型制造出来的每辆汽车就是一个对象。
类的定义
python
使用class
关键字定义一个类:
class Human: # 定义了一个“人”类
在给类起名字时,最好使用能代表该类功能的单词,例如用Student
作为学生类的类名;甚至如果必要,可以使用多个单词组合而成,例如初学者定义的第一个类的类名可以是TheFirstDemo
。
注意,如果由单词构成类名,建议每个单词的首字母大写,其它字母小写。
给类起好名字之后,其后要跟有冒号:
,表示告诉Python
解释器,下面要开始设计类的内部功能了,也就是编写实例属性和实例方法。
class Human: # 定义一个类
def __init__(self): # 类的构造函数
self.name = "中本聪" # 定义name实例属性
self.age = 50 # 定义age实例属性
def eat(self): # 定义一个实例方法
print("吃")
def drink(self): # 定义一个实例方法
print("喝")
def sleep(self): # 定义一个实例方法
print("睡")
创建对象
创建对象的过程称为实例化
,因此创建的对象也叫作实例对象
。
zhongbencong = Human() # 实例化一个对象zhongbencong
print(zhongbencong.name) # 访问zhongbencong这个实例对象的实例属性
zhongbencong.eat() # 调用实例方法
本节课回顾
这节课我们主要了解了Python
中的三种编程方式:面向过程、面向函数、面向对象。我们也介绍了面向对象编程方式的业务场景以及它的优点。面向对象编程是通过使用类和对象的方式来实现的,我们学习了Python
中如何去定义类、如何创建对象以及如何在创建对象后查看其属性和调用方法。下一节课我们会继续为大家介绍实例属性和方法以及__init__
构造函数、如何理解self
。
因为面向对象这一块的知识呢比较抽象,大家刚接触可能理解起来有些困难,俗话说知行合一,那我们在以后的实践过程中多写多练,就能够慢慢理解了。
网友评论