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','张进购买了一个学位课')
View Code

  面向对象式编程 :

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','张进购买了一个学位课')
View Code

对比结果 :

  函数 : 定义简单/调用简单

  面向对象 : 定义复杂/调用复杂       好处 : 归类,将某些类似的函数写在一起

总结:

  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
View Code

 方法二 : 在指定类中编写和当前类相关的所有代码 + 提取公共值

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()
View Code

面向对象三大特性: (封装/继承/多态)

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)
python中多态

  在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)
Java中多态

 

posted @ 2018-08-27 15:02  葡萄想柠檬  Views(228)  Comments(0)    收藏  举报
目录代码