1.概要
# 面向过程:根据业务逻辑从上到下写垒代码 # 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 # 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
2. 函数式编程和面向对象对比
# 需求:请开发一个消息提醒的功能(邮件 / 短信 / 微信) (1)函数实现: def email(em, text): """ 发送邮件 :return: """ print(em, text) def msg(tel, text): """ 发送短信 :return: """ print(tel, text) def wechat(num, text): """ 发送微信 :return: """ print(num, text) # 编写功能:假设用户购买课程,然后给alex发送提醒; if 1 == 1: msg('188888888', '张进购买了一个学位课') email('alex@sb.com', '张进购买了一个学位课') wechat('xxxx', '张进购买了一个学位课') (2)面向对象实现: class Message: def email(self, em, text): """ 发送邮件 :return: """ print(em, text) def msg(self, tel, text): """ 发送短信 :return: """ print(tel, text) def wechat(self, num, text): """ 发送微信 :return: """ print(num, text) # 编写功能:假设用户购买课程,然后给alex发送提醒; if 1 == 1: obj = Message() obj.email('alex@sb.com', '张进购买了一个学位课') obj.msg('188888888', '张进购买了一个学位课') obj.wechat('xxxx', '张进购买了一个学位课') 对比: 函数: 定义简单 / 调用简单 面向对象: 定义复杂 / 调用复杂 好处: 归类, 将某些类似的函数写在一起 总结: 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()
3. 面向对象代码如何编写
3.1 创建类和对象 (1)类和对象 面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用 类: 类就是一个模板,模板里可以包含多个函数,函数里实现一些功能 对象: 对象则是根据模板创建的实例,通过实例对象可以执行类中的函数 (2) 创建类和对象如下图
class是关键字,表示类
创建对象,类名称后加括号即可
ps:类中的函数第一个参数必须是self(详细见:类的三大特性之封装)
类中定义的函数叫做 “方法”
3.2 构造方法(函数) (1)什么是构造方法? 示例1 class Foo: def __init__(self,name): # 特殊的方法(构造方法),如果 类名(),则该方法会被自动执行,目的进行数据初始化。 self.name = name self.age = 18 obj = Foo('闫康琪') 类名+括号 -> 实例化(创建对象),会自动触发__init__(构造函数)
总结: (1)通过构造方法可以将数据进行打包,以后使用时,去其中获取即可
(2)__init__(构造方法)是一个特殊的方法,在对象实例化时会被调用,它的作用是初始化 示例2 class Bar: pass obj = Bar() # 类后面写了个空的,表示类里面没有构造方法 (2)应用 a.将数据封装到对象中, 以供自己在方法中调用 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() # ... pass def read_last(self): # self.f.read() # ... pass def read_second(self): # self.f.read() # ... pass obj = FileHandler('C:/xx/xx.log') obj.read_first() obj.read_last() obj.read_second() obj.f.close() b.将数据封装到对象中, 以供其它数据调用 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(111, 222, 333) new_func(obj) c.在类的方法内部调用类中的其他方法 class UserInfo: def __init__(self): self.name = None def info(self): print("当前用户名称:%s" % (self.name)) def account(self): print("当前用户%s的账单是:..." % (self.name)) def shopping(self): print("当前用户%s购买了一个人形抱枕" % (self.name)) def login(self): user = input("请输入用户名:") pwd = input("请输入密码:") if pwd == 'sb': self.name = user while 1: print(""" 1. 查看用户信息 2. 查看用户账单 3. 购买抱枕 """) num = int(input("请输入选择的序号:")) if num == 1: self.info() elif num == 2: self.account() elif num == 3: self.shopping() else: print("序号不存在,请重新输入") else: print("登陆失败") obj = UserInfo() obj.login()
3.3 规则 class Foo: # 创建类 def __init__(self): # 构造函数 self.name = name def detail(self,msg): # 其他函数 print(self,name,msg) obj = Foo() #创建对象/实例化 obj.detail() # 通过对象执行内部的方法 实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征 实例化的过程就是: 类——>对象的过程
3.4 什么时候写?如何写? 方式一: 归类 + 提取公共值 归类: class File: def file_read(self, file_path): pass def file_update(self, file_path): pass def file_delete(self, file_path): pass def file_add(self, file_path): pass class Excel: def excel_read(self): pass def excel_update(self): pass def excel_delete(self): pass def excel_add(self): pass 提取公共值: class File: def __init__(self, file_path): self.file_path = file_path def file_read(self): pass def file_update(self): pass def file_delete(self): pass def file_add(self): pass class Excel: def __init__(self, file_path): self.file_path = file_path def excel_read(self): pass def excel_update(self): pass def excel_delete(self): pass def excel_add(self): pass 方式二: 在指定类中编写和当前类相关的所有代码 + 提取公共值 class Message: def email(self): pass 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 = fig - 10 def practice(self): # 自我修炼 self.fight = fig + 90 def incest(self): # 多人游戏 self.fight = fig - 666 cang = Person('苍井井', '女', 18, 1000) # 创建苍井井角色 dong = Person('东尼木木', '男', 20, 1800) # 创建东尼木木角色 bo = Person('波多多', '女', 19, 2500) # 创建波多多角色 dong.grassland() # 东尼木木草丛战斗
4. 面向对象的三大特性: 封装/继承/多态
4.1 封装 (1) 将相关功能封装到一个类中 class Message: def email():pass def msg():pass def wechar():pass (2) 将数据封装到一个对象中 class Person: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender obj = Person('闫子哲',26,'男')
封装的用法: (1)将相关功能封装到一个类中
(2)将数据封装到一个对象中
4.2 继承 (1)单继承: 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() # 原则:先在自己类中找,没有就去父类中找 (2)多继承 class Base1: def show(self): print('Base1.show') class Base2: def show(self): print('Base2.show') class Foo(Base1,Base2): pass obj = Foo() obj.show() # Base1.show # 原则左边父类的更亲,先去找左边的父类 总结: 1. 继承编写 class Foo(父类): pass 2. 支持多继承(先找左/再找右) # java不支持多继承 3. 为什么要有多继承? 提高代码重用性 练习: 找到self到底是谁的对象? 从谁开始找 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() # 1. 多继承先找左边的 # 2. self到底是谁,self是哪个类的对象,那么就从该类开始找(自己没有就找父类) obj = Foo() obj.f0() 结果: foo.f0 base2.f3 base1.f1
4.3 多态 多种形态或多种状态 鸭子模型,只要可以嘎嘎叫就是鸭子. python # 由于python原生支持多态,所以没有什么特殊性 class Foo1: def f1(self): pass class Foo2: def f1(self): pass class Foo3: def f1(self): pass def func(arg): # 这里的传进来的arg可以是多种形态的 arg.f1() obj = Foo1() # obj = Foo2() obj = Foo3() func(obj) # 这里obj可以是Foo2(), 也可以是 Foo3() # java class Son(list): pass class Son1(list): pass # 以后传参时,arg可以是:list类的对象/list任何子类的对象 public void func(list arg){ print(arg) } # obj = list() # obj = Son() obj = Son1() func(obj)
5. 本节重点
1. 编写方式+执行流程 2. 如何归类? 反向:归类+提取公共值 反向->把函数写出来了再归类,写出来了再改面向对象,耗时间 正向:类相关的功能+提取公共值 正向->写好类,直接在类下面写方法,在脑子里提前设计好 3. 三大特性
封装/继承/多态