面向对象的初识
转自https://www.cnblogs.com/schut/p/8541547.html
一、面向过程
1、面向过程:核心是过程二字,过程指的是解决问题的步骤,好比如设计一条流水线,是一种机械式的思维方式。
就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。
2、优缺点:
优点:将复杂的问题流程化,进而简单化。
缺点:扩展性差
3、实例:面向过程式的登录注册程序
import json,re def login(): ''' 用户输入 :return: ''' usename = input('用户名:').strip() pwd = input('密码:').strip() tel = input('电话:').strip() mail = input('邮箱:').strip() return { 'usename':usename, 'pwd':pwd, 'tel':tel, 'mail':mail } def authentication(use_info): ''' 判断用户名和密码等信息是否合法 :return: ''' is_valid = True # 默认合法 if len(use_info['usename'])==0: print('用户名不能为空!') is_valid = False if len(use_info['pwd'])< 6: print('密码长度不得小于6位!') is_valid = False if len(re.findall('1[0-9]{10}',use_info['tel']))==0: print('电话格式不对!') is_valid = False if not re.search(r'@.*?.com$',use_info['mail']).group(): # 使用Python的r前缀,就不用考虑转义的问题,'*'加个?就可以让'.'采用非贪婪匹配 print('邮箱格式不对') is_valid = False return { 'valid':is_valid, 'info':use_info } def register(auth): ''' 若输入信息合法则注册,写入文件或数据库 :param auth: :return: ''' if auth['valid']==True: with open('data.json','w',encoding='utf-8') as f: json.dump(auth['info'],f) def main(): ''' 主逻辑程序 :return: ''' use_info = login() auth = authentication(use_info) register(auth) if __name__=='__main__': # 直接调用时执行下列程序,被调用时不执行 main()
注意:一般认为, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的,但如果你要处理的任务是复杂的,且需要不断迭代和维护 的, 那还是用面向对象最方便。
二、面向对象
1、面向对象:核心是对象二字,特征和技能的结合体。
2、优缺点:
优点:可扩展性高
缺点:编程复杂度高
3、应用场景:用户需求经常变化,互联网应用,游戏,企业内应用等。
4、关于面向对象的几个名词解释
类:一个类即是对一系列对象相似的特征和技能的结合体,如同一个模板。在类中定义了这些对象的都具备的属性,共同的方法。
属性:人类包含很多特征,把这些特征用程序来描述的话,叫做属性,比如年龄、身高、性别、姓名等都叫做属性,一个类中,可以有多个属性。
方法:人类不止有身高、年龄、性别这些属性,还能做好多事情,比如说话、走路、吃饭等,相比较于属性是名词,说话、走路是动词,这些动词用程序来描述就叫做方法。
实例(对象):一个对象即是一个类的实例化后的实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同。
实例化:把一个类转变为一个对象的过程就叫实例化。
5、简单实例
# 现实世界中的对象: ''' 对象1 特征 职业:学生 姓名:王二 性别:男 年龄:22 技能 学习 打游戏 对象2 特征 职业:学生 姓名:张三 性别:男 年龄:20 技能 学习 打游戏 看书 对象3 特征 职业:学生 姓名:婉婉 性别:女 年龄:18 技能 学习 打游戏 看书 现实中的类: 特征: 职业:学生 技能: 学习 打游戏 看书 在程序中: ''' # 先有类 class School_learn: job = 'student' def study(self): print('study hard!') def play_game(self): print('play games as little as you can') def read(self): print('read books more and more') # 再调用类产生对象 student1 = School_learn() student2 = School_learn() student3 = School_learn() print(student1) # <__main__.School_learn object at 0x000002B70F8D7588> 对象 print(student2) print(student3)
6、面向对象三大特性 <1>封装(Encapsulation):在类中对数据的赋值、内部调用对外部用户来说是透明不可见的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法。 <2>继承(Inheritance):一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承。 <3>多态(Polymorphism):多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。 注意:这里只是简单说明下几大特性,后续我们会深入探讨的的。
def func(arg):
pass
func(1)
func(2)
1. 函数式编程和面向对象的对比
a. round 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','张进购买了一个学位课') 面向对象: 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()
b. 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,'男') 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('侯明魏') 通过构造方法,可以将数据进行打包,以后使用时,去其中获取即可. 示例二: 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... # ... 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,22,333) new_func(obj)
练习: 信息管理系统 1. 用户登录 2. 显示当前用户信息 3. 查看当前用户所有的账单 4. 购买姑娘形状的抱枕 示例: 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 True: 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() 总结: class Foo: def func2(self): print('func2') def func1(self): self.fun2() print('func1') obj = Foo() obj.func1() 2. 面向对象代码如何编写 a. 规则 class Foo: def __init__(self,name): self.name = name def detail(self,msg): print(self.name,msg) obj = Foo() obj.detail() b. 什么时候写?如何写? 方式一:归类+提取公共值 归类: 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,file_path): pass def excel_update(self,file_path): pass def excel_delete(self,file_path): pass def excel_add(self,file_path): 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 = 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() 3. 面向对象的三大特性:封装/继承/多态 封装: 将相关功能封装到一个类中: class Message: def email(self):pass def msg(self):pass def wechat(self):pass 将数据封装到一个对象中: class Person: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender obj = Person('孙福来',18,'女') 继承: 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() # 原则:现在自己类中找,么有就去父类 总结: 1. 继承编写 class Foo(父类): pass 2. 支持多继承(先找左/再找右) 3. 为什么要有多继承? 提供代码重用性 练习: 找self到底是谁的对象?从谁开始找. 多态: 多种形态或多种状态 鸭子模型,只要可以嘎嘎叫就是鸭子. 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) """ 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) 重点: 1. 编写方式执行流程 2. 如何归类? 反向:归类+提取公共值 正向:类相关的功能+提取公共值 3. 三大特性
""" 练习: 信息管理系统 1. 用户登录 2. 显示当前用户信息 3. 查看当前用户所有的账单 4. 购买姑娘形状的抱枕 """ 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 True: 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()
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
# by luffycity.com """""" # ########################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() # 原则:现在自己类中找,么有就去父类 """ # ##### 为何有继承? 为了提高代码重用性 """ class Base: def f1(self): pass class Foo(Base): def f2(self): pass class Bar(Base): def f3(self): pass """ # ########################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() """ # 左边更亲 # ############################### 练习题 ############################# ###### 习题1 # class Base: # def f1(self): # print('base.f1') # # class Foo(Base): # def f2(self): # print('foo.f2') # 1. 是否执行 # obj = Foo() # obj.f2() # obj.f1() # 2. 是否执行 # obj = Base() # obj.f1() # obj.f2() # 错 ##### 习题2: """ class Base: def f1(self): print('base.f1') class Foo(Base): def f3(self): print('foo.f3') def f2(self): print('foo.f2') self.f3() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. obj = Foo() obj.f2() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. """ ##### 习题3: """ class Base: def f1(self): print('base.f1') def f3(self): print('foo.f3') class Foo(Base): def f2(self): print('foo.f2') self.f3() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. obj = Foo() obj.f2() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. """ ##### 习题4: """ class Base: def f1(self): print('base.f1') def f3(self): self.f1() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. print('foo.f3') class Foo(Base): def f2(self): print('foo.f2') self.f3() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. obj = Foo() obj.f2() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. """ ##### 习题5: """ class Base: def f1(self): print('base.f1') def f3(self): self.f1() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. print('base.f3') class Foo(Base): def f1(self): print('foo.f1') def f2(self): print('foo.f2') self.f3() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. obj = Foo() obj.f2() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. # foo.f2 # foo.f1 # base.f3 obj2 = Base() obj2.f3() # base.f1 # base.f3 """ # 总结: self是那个类的对象,那么就从该类开始找(自己没有就找父类) ##### 习题6: class Base1: def f1(self): print('base1.1') 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()