一, 面向对象简介
Python 设计之初, 就是一门面向对象的语言, 在 Python 中一切皆对象, 而且在 Python 中创建一个对象也很简单, 今天我们就来学习一下 Python 的面向对象的知识.
二, 两种编程方式
在 C#,Java 中, 只能使用面向对象编程, 在 Ruby,Python 中可以使用函数编程以及面向对象进行编程.
函数式编程
- def fetch(backend):
- pass
- def add_record(backend,record):
- pass
- fetch("www.oldboy.org")
- add_record("www.oldboy.org",xxxxx)
面向对象编程
- class Oldboy:# 类, 用来封装几个函数
- def fetch(self,backend):#self 是 python 内部传的, 用户我们传值时
- pass #传的第一个参数直接给 backend
- def add_record(self,backend,record):
- pass
- obj = Oldboy()
- obj.fetch()
函数在类的外面就叫做函数, 在类的里面就叫做方法, 面向对象的情况下想要执行函数时需要根据这个类创建一个对象, 通过对象访问函数.
一般函数式编程的函数为模块的成员, 而面向对象编程, 类是模块的成员, 函数是类的成员.
面向对象的程序设计的核心是对象 (上帝式思维), 要理解对象为何物, 必须把自己当成上帝, 上帝眼里世间存在的万物皆为对象, 不存在的也可以创造出来. 对象是特征和技能的结合, 其中特征和技能分别对应对象的数据属性和方法属性.
优点是: 解决了程序的扩展性. 对某一个对象单独修改, 会立刻反映到整个体系中, 如对游戏中一个人物参数的特征和技能修改都很容易.
缺点: 可控性差, 无法向面向过程的程序设计流水线式的可以很精准的预测问题的处理流程与结果, 面向对象的程序一旦开始就由对象之间的交互解决问题, 即便是上帝也无法预测最终结果. 于是我们经常看到一个游戏人某一参数的修改极有可能导致阴霸的技能出现, 一刀砍死 3 个人, 这个游戏就失去平衡.
三, 面向对象深度解析
1. 关于 self 的解析
2. 封装
- class Oldboy:
- def fetch(self):
- print(self.backend)# 因为参数 self 传的值为对象 obj1, 所以可以用 self 代替 obj1
- def add_record(self,record):
- pass
- obj1 = Oldboy()
- obj1.backend = "alexsel"# 这个参数, 和 obj1 一起被存入内存
- # 封装的非主流的方式
- obj1.fetch()# 由于 backend 和 obj1 一起存入内存, 所以不用再吧 backend 传过去, 直接
- #在函数里用 self.backend 使用
- obj2 = Oldboy()
- obj2.backend = "ALEXSEL"
- obj2.fetch()
这里也显示出了 self 的作用, self 可以标识对象, 由于给两个对象传入的参数输不同, 调用类的方法的时候, 输出的内容就不同, 这就是 self 的功能.
应用:
当有几个函数要传的参数相同时, 封装比较简便
3. 构造方法__init__
当使用类创建对象的时候 (obj = Foo()), 默认执行__init__方法
- class Foo:
- def __init__(self, bk): ## 这个 self 为创建的对象, 创建对象时默认执行__init__
- print("init") ## 所以可把需要多次传的参数在这里创建, 代替上面那个
- self.name = "alex" ## 非主流的方法
- self.favor = bk
- print(self.favor)
- # 创建对象, 实例, 并将 "xxx" 封装到对象里
- obj1 = Foo("xxx") # 创建对象时, 类里就会执行__init__方法 (函数), 这个 xxx 就传入到__init__的 bk 参数中
- obj2 = Foo("sss")
输出结果:
- init
- xxx
- init
- sss
使用场景: 当同一类型的的方法具有相同的参数时, 直接封装到对象即可.
使用场景: 把类当成模板, 创建多个对象 (对象内封装的数据可以不一样).
四, 上手练习
针对刚才了解的知识, 我们进行一个简单的练习, 输出同样的结果下, 不同的两种写法, 熟悉类中方法和属性的使用.
写法一:
- class activity:
- def __init__(self,name,age,gender):
- self.FlyAnAeroplane = "{:s},{:s},{:s}, 去开飞机".format(name,age,gender)
- self.GoToSchool = "{:s},{:s},{:s}, 去学校".format(name,age,gender)
- self.Farm = "{:s},{:s},{:s}, 去种田".format(name,age,gender)
- def FlyAnAeroplane_one(self):
- print(self.FlyAnAeroplane)
- def GoToSchool_one(self):
- print(self.GoToSchool)
- def Farm_one(self):
- print(self.Farm)
- obj = activity("alexsel","10","男")
- obj.FlyAnAeroplane_one()
- obj.GoToSchool_one()
- obj.Farm_one()
- obj2 = activity("eric","60","男")
- obj2.FlyAnAeroplane_one()
- obj2.GoToSchool_one()
- obj2.Farm_one()
输出结果:
alexsel,10, 男, 去开飞机
alexsel,10, 男, 去学校
alexsel,10, 男, 去种田
eric,60, 男, 去开飞机
eric,60, 男, 去学校
eric,60, 男, 去种田
写法二:
- class Foo:
- def __init__(self, name, age, gender):
- self.name = name
- self.age = age
- self.gender = gender
- def kaifeiji(self):
- print("%s,%s 岁,%s, 去开飞机" % (self.name, self.age, self.gender))
- def quxuexiao(self):
- print("%s,%s 岁,%s, 去学校" % (self.name, self.age, self.gender))
- def quzhongtian(self):
- print("%s,%s 岁,%s, 去种田" % (self.name, self.age, self.gender))
- alexsel = Foo('alexsel', 10, '男')
- alexsel.kaifeiji()
- alexsel.quxuexiao()
- alexsel.quzhongtian()
- eric = Foo('eric', 90, '男')
- eric.kaifeiji()
- eric.quxuexiao()
- eric.quzhongtian()
输出结果:
alexsel,10 岁, 男, 去开飞机
alexsel,10 岁, 男, 去学校
alexsel,10 岁, 男, 去种田
eric,90 岁, 男, 去开飞机
eric,90 岁, 男, 去学校
eric,90 岁, 男, 去种田
五, 项目练习
在写这个项目之前, 我们首先学习一下 pickel 模块.
pickle 可以将任何数据类型序列化, pickle 只能在 python 中使用, pickle 模块用于将内存中的 python 对象序列化成字节流, 并可以写入任何类似文件对象中; 它也可以根据序列化的字节流进行反序列化, 将字节流还原为内存中的对象.
pickle 使用 dump 方法将内存对象序列化:
- import pickle
- li = list(range(1,3))
- dbfile = open('pickle_list', 'wb') #必须以 2 进制打开文件, 否则 pickle 无法将对象序列化只文件
- pickle.dump(li, dbfile)
- dbfile.close()
以上代码即将 list 对象 li 序列化至文件 "pickle_list" 中, 下次再次运行时, 可以通过 pickle 的 load 方法恢复 list 对象:
- import pickle
- dbfile = open('pickle_list', 'rb')
- li = pickle.load(dbfile)
- dbfile.close()
开始项目练习
- import pickle
- class Person:
- def __init__(self,name,age,weight):
- self.Name = name
- self.Age = age
- self.Weight = weight
- def eat(self):
- self.Weight = self.Weight + 2 #每次吃饭, 体重加 1
- def fitness(self):
- self.Weight = self.Weight - 1 #每次健身, 体重减 1
- xiaoming = pickle.load(open("fitnessgame.obb","rb"))
- if xiaoming: #判断是否有小明这个对象, 没有创建小明对象
- print(xiaoming.Weight)
- xiaoming.fitness()
- xiaoming.fitness()
- xiaoming.fitness()
- print(xiaoming.Weight)
- pickle.dump(xiaoming,open("fitnessgame.obb","wb"))
- else:
- xiaoming = Person("小明","10 岁",200)
- xiaoming.fitness()
- xiaoming.eat()
- xiaoming.eat()
- xiaoming.eat()
- xiaoming.eat()
- print(xiaoming.Weight)
- pickle.dump(xiaoming,open("fitnessgame.obb","wb"))
明天我们接着讲面向对象, 明天继续讲面向对象中的继承.
来源: https://www.cnblogs.com/liudi2017/p/9286742.html