面向对象初识
一、函数式编程和面向对象的对比
面向过程:根据业务逻辑从上到下垒代码;
函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可;
面向对象:对函数进行分类和封装,让开发“更快更好更强...”;
面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。
round 1 请开发一个消息提醒的功能(邮件/短信/微信)
def email(em,text): """ 发送邮件 """ print(em,text) def msg(tel,text): """ 发送短信 """ print(tel,text) def wechat(num,text): """ 发送微信 """ print(num,text) # 编写功能:假设用户购买课程,然后给管理员发送提醒; if 1==1: msg('188888888','xx购买了一个学位课') email('alex@sb.com','xx购买了一个学位课') wechat('微信号','xx购买了一个学位课')
class Message: def email(self, em, text): """ 发送邮件 """ print(em,text) def msg(self, tel, text): """ 发送短信 """ print(tel,text) def wechat(self, num, text): """ 发送微信 """ print(num,text) # 编写功能:假设用户购买课程,然后给管理员发送提醒; if 1==1: obj = Message() obj.email('alex@sb.com', 'xx购买了一个学位课') obj.msg('188888888','xx购买了一个学位课') obj.wechat('微信号','xx购买了一个学位课')
通过第一轮对比,我们发现:
函数式的特点是:定义简单,调用简单;
面向对象的特点是:定义复杂,调用复杂,其好处是进行了归类,将某些类似的函数写在了一起。
总结:1、函数式编程可能会比面向对象好;
2、python中支持两种编程方式;
3、面向对象编程方式格式如下:
定义:
class 类名: -- 定义了一个类
def 函数名(self): -- 在类中编写了一个"方法"
pass
调用:
x1 = 类名() -- 创建了一个对象/实例化一个对象
x1.函数名() -- 通过对象调用其中一个方法.
4、面向对象编程示例:
class Account: def login(self): user = input('请输入用户名:') pwd = input('请输入密码:') if user == 'alex' and pwd == 'sb': print('登录成功') else: print('登录失败') obj = Account() obj.login()
round 2 打印:完成以下功能:
老狗/20岁/男/上山去砍柴
老狗/20岁/男/开车去东北
老狗/20岁/男/喜欢大宝剑
def kc(name,age,gender): data = "%s,性别%s,今年%s岁,喜欢上山砍柴" %(name,gender,age) print(data) def db(name,age,gender): data = "%s,性别%s,今年%s岁,喜欢开车去东北" %(name,gender,age) print(data) def bj(name,age,gender): data = "%s,性别%s,今年%s岁,喜欢大宝剑" %(name,gender,age) print(data) kc('老狗',20,'男') db('老狗',20,'男') bj('老狗',20,'男')
class LaoGou: def __init__(self,name,age,gender): # 特殊的方法,如果 类名() ,则该方法会被自动执行 (构造方法) self.n1 = name self.n2 = age self.n3 = gender def kc(self): data = "%s,性别%s,今年%s岁,喜欢上山砍柴" %(self.n1,self.n3,self.n2) print(data) def db(self): data = "%s,性别%s,今年%s岁,喜欢开车去东北" %(self.n1,self.n3,self.n2) print(data) def bj(self): data = "%s,性别%s,今年%s岁,喜欢大宝剑" %(self.n1,self.n3,self.n2) print(data) obj = LaoGou('老狗',20,'男') obj.kc() obj.db() obj.bj()
总结:1、构造方法
# 示例一: class Foo: def __init__(self,name): # 构造方法,目的是进行数据初始化. self.name = name self.age = 18 # 也可以指定值,不一定非要传参 obj = Foo("alex") # 通过构造方法,可以将数据进行打包,以后使用时,去其中获取即可. # 示例二: class Bar: pass obj = Bar()
2、面向对象编程应用:
2.1 将数据封装到对象中,以供自己在方法中调用,如下示例:
class FileHandler: def __init__(self, file_path): self.file_path = file_path self.f = open(self.file_path, 'rb') def read_first(self): # self.f.read() # ... def read_last(self): # self.f.read() # ... def read_second(self): # self.f... # ... obj = FileHandler('C:/xx/xx.log') obj.read_first() obj.read_last() obj.read_second() obj.f.close()
2.2 将数据封装到对象中,以供其他函数调用,如下示例:
def new_func(arg): arg.k1 arg.k2 arg.k6 class Foo: def __init__(self,k1,k2,k6): self.k1 = k1 self.k2 = k2 self.k6 = k6 obj = Foo(11,22,66) new_func(obj)
注:Java和C#只支持面向对象编程,而python比较灵活既支持面向对象编程也支持函数式编程。
二、面向对象代码如何编写
1、面向对象代码语法规则,如下示例:
class Foo: def __init__(self, name): self.name = name def detail(self, msg): print(self.name, msg) obj = Foo("alex") obj.detail("hello world")
2、什么时候写面向对象代码?如何写?
2.1 反向:归类 + 提取公共值;
2.2 正向:在指定类中编写和当前类相关的所有代码 + 提取公共值;如下示例:
class Person: def __init__(self, na, gen, age, fig): self.name = na self.gender = gen self.age = age self.fight = fig def grassland(self): self.fight = self.fight - 10 def practice(self): self.fight = self.fight + 90 def incest(self): self.fight = self.fight - 666 cang = Person('苍井井', '女', 18, 1000) # 创建苍井井角色 dong = Person('东尼木木', '男', 20, 1800) # 创建东尼木木角色 bo = Person('波多多', '女', 19, 2500) # 创建波多多角色 dong.grassland()
二、面向对象三大特征:封装、继承、多态
1、封装
1.1 将相关方法封装到一个类中,如下示例:
class Message: def email(self):pass def msg(self):pass def wechat(self):pass
1.2 将数据封装到一个对象中,如下示例:
class Person: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender obj = Person('alex', 18, '男')
2、继承(原则:先在自己类中找,没有就去父类中找)
如下示例:
class SuperBase: def f3(self): print('f3') class Base(SuperBase): # 父类, 也称基类 def f2(self): print('f2') class Foo(Base): # 子类,也称派生类 def f1(self): print('f1') obj = Foo() obj.f1() obj.f2() obj.f3() # 父类和子类都是相对的,此例中Base是SupperBase的子类,是Foo的父类
总结:1)继承编写规则,如下:
class Foo(父类名):
pass
2)支持多继承,即一个子类可以有多个父类(先找左边父类,再找右边);
3)为什么要有继承和多继承?提高代码的可重用性;
继承的相关练习题:
class Base1: def f1(self): print('base1.f1') def f2(self): print('base1.f2') class Base2: def f1(self): print('base2.f1') def f2(self): print('base2.f2') def f3(self): print('base2.f3') self.f1() class Foo(Base1,Base2): def f0(self): print('foo.f0') self.f3() obj = Foo() # 实例化Foo类的一个obj对象 obj.f0() # 结果为: # foo.f0 # base2.f3 # base1.f1
总结:1)多继承先找左边;
2)明确self到底是谁,self是哪个类的对象,那么就从该类开始找(自己没有就找父类);
3、多态
鸭子模型,只要可以嘎嘎叫就是鸭子。由于Python函数传参时,无需指定类型。
def func(arg): # arg可以是多种类型,只要其中有send方法即可. arg.send()
多态就是多种形态或多种状态,由于python原生支持多态,所以没有特殊性,如下是体现python原生多态的示例:
class Foo1: def f1(self): pass class Foo2: def f1(self): pass class Foo3: def f1(self): pass def func(arg): arg.f1() obj = Foo1() # obj= Foo2() obj = Foo3() func(obj) # func的参数可以是Foo1的实例化对象,也可以是Foo2或者Foo3的实例化对象