Python全栈开发之路 【第七篇】:面向对象编程设计与开发(1)

本节内容

一、编程范式

编程指的是写程序、敲代码,就是指程序员用特定的语法、数据结构和算法编写的代码,目的是来告诉计算机如何执行任务的。

在编程的世界里最常见的两大流派是:面向过程与面向对象。“功夫的流派没有高低之分,只有习武的人才有高低之分“,在编程世界里更是这样,面向过程与面向对象在不同的场景下都各有优劣,谁好谁坏不能一概而论。

二、面向过程的程序设计

核心是“过程”二字,“过程”指的是解决问题的步骤,即先干什么再干什么......,基于面向过程设计程序就好比在设计一条流水线,是一种机械式的思维方式。

优点:复杂问题简单化。

# 写一个数据远程备份程序,
#分三步,本地数据打包,上传至云服务器,测试备份文件可用性
import os def data_backup(folder):
print("找到备份目录: %s" %folder)
print('正在备份......')
zip_file='/tmp/backup20181103.zip'
print('备份成功,备份文件为: %s' %zip_file)
return zip_file def cloud_upload(file):
print("\nconnecting cloud storage center...")
print("cloud storage connected.")
print("upload file...%s...to cloud..." %file)
link='http://www.xxx.com/bak/%s' %os.path.basename(file)
print('close connection.....')
return link def data_backup_test(link):
print("\n下载文件: %s , 验证文件是否无损" %link) def main():
#步骤一:本地数据打包
zip_file = data_backup("c:\\users\\alex\欧美100G高清无码") #步骤二:上传至云服务器
link=cloud_upload(zip_file) #步骤三:测试备份文件的可用性
data_backup_test(link) if __name__ == '__main__':
main()

面向过程的例子

缺点:扩展性极差。

应用场景:

  面向过程的程序设计思想一般用于那些功能一旦实现之后就很少需要改变的场景, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,著名的例子有Linux內核,git,以及Apache HTTP Server等。但如果你要处理的任务是复杂的,且需要不断迭代和维护 的, 那还是用面向对象最方便了。

三、面向对象的程序设计

核心是“对象”二字,要理解对象为何物,必须把自己当成上帝,在上帝眼里,世间存在的万物皆为对象,不存在的也可以创造出来,与面向过程机械式的思维方式形成鲜明对比,面向对象更加注重对现实世界而非流程的模拟,是一种“上帝式”的思维方式。

优点:可扩展性高。

缺点:编程的复杂度远高于面向过程。

应用场景:当然是应用于需求经常变化的软件中,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方。

四、类与对象

对象是特征与技能的结合体,而类是一系列对象相似的特征与技能的结合体。

在现实世界中:肯定是先有对象,再有类;

在程序中:要先定义 类,后产生对象。

定义类

按照上述步骤,我们来定义一个类(我们站在学校的角度去看,在座的各位都是学生)

>>>在现实世界中,先有对象,再有类

对象1:李坦克
特征:
学校=实中
姓名=李坦克
性别=男
年龄=18
技能:
学习
吃饭
睡觉 对象2:王大炮
特征:
学校=实中
姓名=王大炮
性别=女
年龄=38
技能:
学习
吃饭
睡觉 对象3:牛榴弹
特征:
学校=实中
姓名=牛榴弹
性别=男
年龄=78
技能:
学习
吃饭
睡觉 现实中的实中的学生类
相似的特征:
学校=实中
相似的技能:
学习
吃饭
睡觉

>>>在程序中,务必保证:先定义(类),后使用类(用来产生对象)

#在Python中程序中的类用class关键字定义,而在程序中特征用变量标识,技能用函数标识,因而类中最常见的无非是:变量和函数的定义
class SchoolStudent:
school='实中'
def learn(self):
print('is learning') def eat(self):
print('is eating') def sleep(self):
print('is sleeping')

注意:

①类中可以有任意的python代码,这些代码在类的定义阶段就会执行,因而会产生新的名称空间,用来存放类的变量名与函数名,通过SchoolStudent.__dict__ 就可以查看。

②类中定义的名字,都是类的属性,点是访问类属性的语法。

类的使用

类属性的 增 删 改 查

SchoolStudent.school #查
SchoolStudent.school='University' #改
SchoolStudent.x=1 #增
del SchoolStudent.x #删

调用类,也成为实例化,得到程序中的对象

s1=SchoolStudent()
s2=SchoolStudent()
s3=SchoolStudent() #如此,s1、s2、s3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__

__init__ 方法

#注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值
# __init__ 方法用来为对象定制对象独有的特征
class LuffyStudents:
school = 'luffycity' # 上下对应 stu1, 'hyp', 22, 'man'
def __init__(self, name, age, sex):
self.Name = name
self.Age = age
self.Sex = sex # 相当于
#stu1.Name = 'hyp'
#stu1.Age = 22
#stu1.Sex = 'man' def learn(self):
print(' is learning') def eating(self):
print(' is eating') # 后产生对象
stu1 = LuffyStudents('hyp', 22, 'man') print(stu1) """
加上__init__ 方法后,实例化的步骤:
1.先产生一个空对象 stu1
2.LuffyStudents.__init__(stu1, 'hyp', 22, 'man')
print(LuffyStudents.__init__) --> 返回的是 类的函数属性
""" # # 查
# print(stu1.__dict__)
# print(stu1.Name)
#
# # 改
# stu1.Name = 'lcy'
# print(stu1.__dict__)
# print(stu1.Name)
#
# # 删除
# del stu1.Name
# print(stu1.__dict__)
#
# # 增加
# stu1.class_name = '全栈开发'
# print(stu1.__dict__) """
# --> 先产生空对象,然后再调__init__,
并传参数 LuffyStudents.__init__(stu2,'lcy', 22, '女')
"""
stu2=LuffyStudents('lcy', 22, '女')

对象的使用

#执行__init__,s1.name='牛榴弹',很明显也会产生对象的名称空间可以用s2.__dict__查看,查看结果为
{'name': '王大炮', 'age': '女', 'sex': 38} s2.name #查,等同于s2.__dict__['name']
s2.name='王三炮' #改,等同于s2.__dict__['name']='王三炮'
s2.course='python' #增,等同于s2.__dict__['course']='python'
del s2.course #删,等同于s2.__dict__.pop('course')

补充:

①站的角度不同,定义出的类是截然不同的;

②现实中的类并不完全等于程序中的类,比如现实中的公司类,在程序中有时需要拆分成部门类,业务类等;

③有时为了编程需求,程序中也可能会定义现实中不存在的类,比如策略类,现实中并不存在,但是在程序中却是一个很常见的类。

五、类的属性查找与绑定方法

类的属性:

  分为  数据属性 和 函数属性。

1、类 的 数据属性 是所有对象共有的,指向的是 同一个内存地址。

#类的数据属性是所有对象共享的,id都一样
print(id(SchoolStudent.school)) print(id(s1.school)) #4377347328
print(id(s2.school)) #4377347328
print(id(s3.school)) #4377347328

2、类的函数属性 是绑定给 对象 用的,称为绑定到对象的方法

#类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样

print(SchoolStudent.learn) #<function SchoolStudent.learn at 0x1021329d8>

print(s1.learn)# 结果:<bound method SchoolStudent.learn of #<__main__.SchoolStudentobject at 0x1021466d8>>

print(s2.learn) # 结果:<bound method SchoolStudent.learn of <__main__.SchoolStudentobject at 0x102146710>>

print(s3.learn) # 结果:<bound method SchoolStudent.learn of <__main__.SchoolStudentobject at 0x102146748>>

#ps:id是python的实现机制,并不能真实反映内存地址,如果有内存地址,还是以内存地址为准

注意:在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常!

绑定方法

先定义 类 并实例化出三个对象

class SchoolStudent:
school='实中'
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def learn(self):
print('%s is learning' %self.name) #新增self.name def eat(self):
print('%s is eating' %self.name) def sleep(self):
print('%s is sleeping' %self.name) s1=SchoolStudent('李坦克','男',18)
s2=SchoolStudent('王大炮','女',38)
s3=SchoolStudent('牛榴弹','男',78)

类中定义的函数(没有被任何装饰器修饰的)是类的函数属性,类可以使用,但必须遵循函数的参数规则,有几个参数就要传几个参数。

SchoolStudent.learn(s1) #李坦克 is learning
SchoolStudent.learn(s2) #王大炮 is learning
SchoolStudent.learn(s3) #牛榴弹 is learning s1.learn() #等同于SchoolStudent.learn(s1)
s2.learn() #等同于SchoolStudent.learn(s2)
s3.learn() #等同于SchoolStudent.learn(s3)

类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象指向的都是相同的功能,但是绑定到不同的对象就是不同的绑定方法。

强调:

  ①绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法__init__也是一样的道理)

  绑定到对象的方法的这种自动传值的特征,决定了在类中定义的函数都要默认写一个参数self,self可以是任意名字,但是约定俗成地写出self。

类即类型

python 中 一切皆对象,且python3 中 类与类型是一个概念,类型就是类 。

#类型dict就是类dict
>>> list
<class 'list'> #实例化的到3个对象l1,l2,l3
>>> l1=list()
>>> l2=list()
>>> l3=list() #三个对象都有绑定方法append,是相同的功能,但内存地址不同
>>> l1.append
<built-in method append of list object at 0x10b482b48>
>>> l2.append
<built-in method append of list object at 0x10b482b88>
>>> l3.append
<built-in method append of list object at 0x10b482bc8> #操作绑定方法l1.append(3),就是在往l1添加3,绝对不会将3添加到l2或l3
>>> l1.append(3)
>>> l1
[3]
>>> l2
[]
>>> l3
[]
#调用类list.append(l3,111)等同于l3.append(111)
>>> list.append(l3,111) #l3.append(111)
>>> l3
[111]
"""
练习一:编写一个学生类,产生一堆学生对象,
要求:
有一个计数器(属性),统计总共实例了多少个对象 """ class Student:
school = 'luffycity' # 数据 属性
count = 0
def __init__(self, name, age, sex): # 类 属性
# self.count += 1
self.name = name
self.age = age
self.sex = sex
Student.count += 1 # 实现共有的属性 累加
# 有几个实例化对象,就会累加几次 def learn(self): # 函数 属性
print('%s is learning ' %self.name) # 实例化出三个对象
stu1 = Student('hyp', 'male', 18)
stu2 = Student('lcy', 'female', 17)
stu3 = Student('alex', 'male', 28) # 只把计数的方法,反映给了 每个对象 独有的特征,不能实现累加
print(stu1.count)
print(stu2.count)
print(stu3.count)
print(stu1.__dict__)
print(stu2.__dict__)
print(stu3.__dict__)
#
print(Student.count) """练习题二:模仿王者荣耀定义两个英雄类
要求:
英雄需要有 昵称、攻击力、生命值 等属性;
实例化出两个英雄对象;
英雄之间可以互殴,被殴打的一方掉血,血量小于0则判定为死亡。
""" class Geren:
camp = 'Demacia' def __init__(self, nickname, life_value, aggersivity):
self.nickname = nickname
self.life_value = life_value
self.aggersivity = aggersivity def attack(self, enemy):
enemy.life_value -= self.aggersivity class Riven:
camp = 'Demacia' def __init__(self, nickname, life_value, aggersivity):
self.nickname = nickname
self.life_value = life_value
self.aggersivity = aggersivity def attack(self, enemy):
enemy.life_value -= self.aggersivity g1 = Geren('草丛伦', 100, 30)
r1 = Riven('锐雯',80,50) g1.attack(r1)

小练习

上一篇:第二篇.2、python基础之字符编码


下一篇:Nagios 监控windows server Apache 服务