一.面向对象:
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) # 编写功能:假设用户购买课程,然后给商家发送提醒; if 1==1: msg('188888888','武松购买了一个学位课') email('wusong@163.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('wusong@163.com', '武松购买了一个学位课') obj.msg('188888888','武松购买了一个学位课') obj.wechat('xxxx','武松购买了一个学位课')
两种写法都有各自的特点:
函数:定义简单/调用简单
面向对象:定义复杂/调用复杂 好处:归类,将某些类似的函数写在一起
由此我们可以看出来函数式编程可能会比面向对象好,而且python中支持这两种编程方式.我们为什么还要用面向对象呢?
面向对象方式格式:
定义:
class 类名: -----定义一个类
def 函数名(self): ------在类中编写一个"方法"
代码块
调用:
n1 = 类名() -----创建了一个对象/实例化一个对象
n1.函数名() ------通过对象调用其中一个方法
# 示例: class Examples: def login(self): user = input("请输入用户名:") pwd = input("请输入密码") if user == 'wusong' and pwd == 'dahu': print("登录成功") else: print("登录失败") obj = Examples() obj.login()
构造方法:
# 示例一: class Foo: def __init__(self,name): #构造方法,目的进行数据初始化. self.name = name self.age = 18 obj = Foo('武大')
通过构造方法,我们可以将数据进行打包,一行使用时,去其中获取即可
要求:输出
老黑/32岁/男/上山去砍柴
老黑/32岁/男/开车去东北
老黑/32岁/男/喜欢大宝剑
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('老黑',32,'男') db('老黑',32,'男') bj('老黑',32,'男')
class LaoHei: def __init__(self,name,age,gender): ## 特殊的方法,如果 类名() ,则该方法会被自动执行 (构造方法) self.n1 = name self.n3 = age self.n2 = 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 = LaoHei('老黑',32,'男') obj.kc() obj.db() obj.bj() obj = LaoHei('小白',18,'女') obj.kc() obj.db() obj.bj()
两种写法对比一下我们会发现,函数想要更该的话需要更改多处地方,而面向对象只更改类名后的参数就行了,方便了很多.构造方法的好处就是这样,能把数据封装到对象中,以供自己函数调用,如以下例子,将打开文件放入到构造方法中,就只需打开一遍就行了,无需多次打开
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()
练习:信息管理系统
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 == '123': 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()
二丶面向对象代码如何编写
方式一:归类+提取公共值
# 归类:将file操作归为一类,excel归为一类 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()
三丶面向对象的三大特性:封装/继承/多态
封装:
将相关功能封装到一个类中:
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()
继承的原则就是现在自己中找,如果没有,再去父类中找, 而父类不能去子类中找,python中的继承支持多继承,就是一个子类可以继承多个父类,查找的顺序是从左到右,这样的多继承能提高代码的重用性.
继承还遵循深度优先和广度优先
多态:
多种形态或者多种状态
由于python原生支持多态,所以没有特殊性
下面看一下java中的多态(伪代码)
Python伪代码实现Java或C#的多态 class F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show' # 由于在Java或C#中定义函数参数时,必须指定参数的类型 # 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类 # 而实际传入的参数是:S1对象和S2对象 def Func(F1 obj): """Func函数需要接收一个F1类型或者F1子类的类型""" print obj.show() s1_obj = S1() Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show s2_obj = S2() Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show