python 面向对象(编写、三大特性)
函数式编程和面向对象的对比
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()
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,'男')
面向对象版本对比结果 :
面向对象版本,可以将参数数据进行打包,在构造函数中进行声明,供类中的方法使用.
总结 :
1. 构造方法
构造方法( __init__(self) ), 目的是进行数据初始化.
通过构造方法可以将数据进行打包,以后使用时,去其中获取即可.
#示例一 class Foo: def __init__(self,name): 构造方法,目的进行数据初始化. 传入参数 name self.name = name self.age = 18 obj = Foo('侯明魏') #示例二: class Bar: # 类中也可以没有构造函数 pass obj = Bar()
2. 应用
1) 将数据封装到对象中,以供自己在方法中调用.
#将数据打包在构造函数中 class FileHandler: def __init__(self,file_path): # 构造函数中除了self,进行传参file_path self.file_path = file_path self.f = open(self.file_path, 'rb') def read_first(self): self.f.read() # 因为文件在构造函数中 self 已经打开文件,这里直接读就好 # ... 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()
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(111,22,333) new_func(obj) # 对象obj作为参数传入函数new_func中
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()
面向对象代码如何编写
1. 规则
类中的方法必须要有 self 参数, 构造函数可有可无, 实例化时,会执行构造函数
class Foo: def __init__(self,name): self.name = name # 在构造函数中 为 self 内部添加参数 name def detail(self,msg): print(self.name,msg) # 次数可以直接调用self中的name 用法为 : self.name obj = Foo('chen') # 实例化时 参数与构造参数保持一致 obj.detail()
2. 什么时候写? 如何写?
方法一 : 归类 + 提取公共值
# 归类: class File: # 关于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: # 关于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 # 将文件路径作为参数,添加到self中,供方法调用 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 # 将文件路径作为参数,添加到self中,供方法调用 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()
面向对象三大特性: (封装/继承/多态)
1. 封装
1) 将相关功能封装到一个类中
class Message: def email(self):pass def msg(self):pass def wechat(self):pass
2) 将数据封装到一个对象中
class Person: def __init__(self,name,age,gender): self.name = name self.age = age self.gender = gender obj = Person('范冰冰',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() # 实例化的是Foo的对象,obj obj.f1() obj.f2() obj.f3() # 原则:先在自己类中找,没有就去父类
1. 继承的编写
class Foo(父类): # 父类写在括号里 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() # Base1.show
3. 为什么要有多继承?
提供代码的重用性
4. 注意 :
在继承中,找方法时, 要找 self 到底是谁的对象, 就从谁开始找. self 并非指的是自己所在的类, 而是要看对象是哪个类的.
1) 多继承先找左边
2) self 到底是谁, self 是哪个类,那么就从该类中找 (自己没有就找父类)
# ############################### 练习题 ############################# ##### 习题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),那么执行方法时,就从该类开始找.并非先从base类中找 print('foo.f3') class Foo(Base): def f2(self): print('foo.f2') self.f3() # obj是哪一个类(Foo),那么执行方法时,就从该类开始找. obj = Foo() obj.f2() # obj是哪一个类(Foo),那么执行方法时,就从该类开始找. ##### 习题5: 注意 self 指的是哪一个对象 class Base: def f1(self): print('base.f1') def f3(self): self.f1() # obj是那一个类(Foo),那么执行方法时,就从该类开始找. 并非base类 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() obj = Foo() obj.f0()
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.f1() obj = Foo1() # obj= Foo2() obj = Foo3() func(obj)
在Java 和 C# 中,编写函数时,传参数需要给定固定的数据类型.
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)

浙公网安备 33010602011771号