您的位置:首页 > 编程语言 > Python开发

python新手入门笔记(八)—— 面向对象

2020-07-22 17:42 197 查看

python新手入门笔记(八)—— 面向对象

  • 面向对象三大特性:封装、继承、多态
  • 多态
  • 总结
  • 概念

    面向过程:根据业务逻辑从上到下写垒代码
    函数式:将某功能代码封装到函数中,日后便无须重复编写,仅调用函数即可。
    面向对象:将数据与函数绑定到一起,进行封装,这样能更快地开发程序,减少重复代码的重写过程。
    注:以上论述非定义,仅描述概念作用。

    类和对象的概念及定义

    类就是一个模板,可包含多个函数,函数里实现功能。相当于图纸。
    对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。相当于根据图纸生产出的具体物品。

    object:基类,其他所有类的

    class Person:
    name = 'xiaoming'
    age = 18
    def eat(self):
    print('吃饭')
    
    xiaoming = Person()
    print(xiaoming.age)
    xiaoming.eat()

    实例方法和属性

    属性:类中定义的变量
    方法:类中定义的函数
    方法有三种:实例方法、类方法、静态方法
    简单来说,函数def xxx(self): 带有self的都是实例方法。

    class Person:
    height = 1.8 # 类属性
    
    def __init__(self):
    # 初始化方法,当对象被创建完成的时候,这个方法会第一个执行,且自动执行
    self.name = '小埋' # 实例属性
    
    # 实例方法
    def text(self):
    print('实例方法')
    
    xm = Person()
    print(xm.height)
    print(xm.name)
    xm.text()
    
    class Person:
    # __init__,对象初始化方法
    def __init__(self,name,age):# self指的就是下方xm对象,即对象本身
    # 初始化方法,当对象被创建完成的时候,这个方法会第一个执行,且自动执行
    self.name = name # 实例属性
    self.age = age
    
    # 实例方法
    def text(self):
    print('实例方法')
    
    xm = Person('小埋',18) # xm是对象,可随意命名,可创建多个对象
    print(xm.name)
    print(xm.age)

    实例方法里的self实际就是我们创建的对象xm。

    class Car:
    def get_self(self):
    print(f'self的id是{id(self)}')
    
    bmw = Car()
    print(id(bmw)) # 2447193969664
    bmw.get_self() # self的id是2447193969664
    ree = Car()
    print(id(ree)) # 2871479535312
    ree.get_self() # self的id是2871479535312

    两者id指向同一个内存空间地址,说明两者是同一个。创建不同对象,id也不同,self的id也只跟随不同的对象发生改变。上例中实际是做出了

    xxx = Car(xxx)
    的处理(Car(xxx) == Car(self))。

    面向对象三大特性:封装、继承、多态

    封装

    1、封装是面向对象编程的一大特点。
    2、把属性和方法封装到一个抽象类中。
    3、外界使用类创建具体的对象,让对象调用具体的方法。
    4、对象方法的细节都被封装在类的内部。

    import random
    
    class Hero:
    def __init__(self,name,konfu):
    self.name = name
    self.blood = 100
    self.kongfu = konfu
    
    def kill(self,enemy):
    '''出招攻击'''
    info = f'{self.name}一招{self.kongfu}攻向了{enemy.name}'
    print(info)
    rand = random.randint(20,40)
    enemy.blood -= rand
    print(f'{enemy.name}掉了{rand}滴血.')
    
    def yun(self):
    '''运功疗伤'''
    rand = random.randint(5,10)
    self.blood += rand
    info = f'{self.name}运功疗伤,加了{rand}滴血。'
    print(info)
    
    def __str__(self): # 模板方法
    return f'{self.name}还剩{self.blood}滴血'
    
    if __name__ == '__main__': # 这段代码下的代码只会在当前文件页生效,常被用作测试使用,该代码无法被导入
    guojing = Hero('郭靖','降龙十八掌') # 创建对象,即为对象分配内存空间,同时init方法为对象设置属性
    wentian = Hero('南宫问天','天外飞仙')
    guojing.kill(wentian)
    wentian.yun()
    print(guojing)
    print(wentian)

    继承

    子类继承父类的属性方法,使子类不需要重复定义父类所拥有的的属性和方法即可调用。即实现代码重用,相同的代码不用重复编写

    class Animal:
    def __init__(self,name):
    self.name = name
    def eat(self):
    print(f'{self.name}吃东西')
    
    def drink(self):
    print('喝东西')
    
    class Dog(Animal):
    pass
    
    class Cat(Animal):
    def miao(self):
    print('喵喵喵')
    
    if __name__ == '__main__':
    wangcai = Dog('旺财')
    wangcai.eat()
    
    Tom = Cat('Tom')
    Tom.miao()

    多继承

    一个子类继承多个父类的属性和方法。

    class A:
    def eat(self):
    print('吃东西a')
    class B:
    def drink(self):
    print('喝东西')
    def eat(self):
    print('吃东西b')
    class C(A,B):
    pass
    
    if __name__ == '__main__':
    c = C()
    c.eat()
    c.drink()

    还有个钻石继承,以后了解。

    重写

    重写父类方法,分为两种情况:
    1、覆盖父类方法

    如果子类和父类拥有同名方法,子类方法会覆盖掉父类方法。

    2、对父类方法的拓展

    父类方法是子类方法的一部分。
    在需要调用父类方法时,在子类方法中使用super().父类方法来调用父类方法。

    对于第一种情况,如下:

    class Base1:
    def test(self):
    print('-------base1--------')
    class Base2:
    def test(self):
    print('-------base2--------')
    class A(Base1):
    def test(self):
    print('---------A----------')
    class B(Base2):
    def test(self):
    print('---------B----------')
    class C(A,B):
    def test(self):
    print('---------c----------')
    
    if __name__ == '__main__':
    c = C()
    c.test() # ---------c----------
    print(C.__mro__) # 继承的搜索路径

    所有的类中都有test方法,但执行结果只有一个,且结果说明两点:

    • 方法就近原则:对象执行方法由最近的类开始寻找,有就执行当前方法,无就继续寻找。
    • 覆盖父类:即重写,子类虽然继承了父类的方法,但子类本身拥有同名方法,子类方法会覆盖掉父类方法。

    对于第二种情况,有三种写法:
    1、父类名.方法名(self,属性名…)
    2、super(子类名,self).方法名()
    3、super().方法名()
    其中第三种是最常用的方法,因为简单。
    注:super是一个类。
    如下:

    class Man:
    def game(self):
    print('玩耍')
    
    class SuperMan(Man):
    def game(self):
    Man.game(self) # 调用父类方法
    super(SuperMan,self).game() # 调用父类方法
    super().game() # 调用父类方法,最常用的方法
    print('飞着玩')
    
    if __name__ == '__main__':
    Clarkent = SuperMan()
    Clarkent.game()

    多态

    多态是由封装和继承引起的一种现象,没有具体的写法。
    指同一种事物的多种形态。
    不同的对象调用相同的方法,产生不同的执行结果,增加代码灵活度

    class Cat:
    def __init__(self,name):
    self.name = name
    
    def game(self):
    print(f'{self.name}愉快地玩耍')
    
    class CatYao(Cat):
    def game(self):
    print(f'{self.name}愉快地在天上玩耍')
    
    class Person:
    def __init__(self,name):
    self.name = name
    
    def game_with_cat(self,cat):
    print(f'{self.name}和{cat.name}愉快地玩耍')
    cat.game()
    
    if __name__ == '__main__':
    # tom = Cat('tom')
    tom = CatYao('tom')
    xiaoming = Person('小埋')
    xiaoming.game_with_cat(tom) # 调用game方法时只需改变类即可改变game方法,即上面tom对象的调用

    多态并无新的语法,只是调用的技巧而已,根据传入对象的不同,实现的方法也不同。

    class A:
    def show(self):
    print('Ashow')
    class B(A):
    def show(self):
    super().show()
    print('Bshow')
    class C:
    def show(self):
    print('Cshow')
    
    class D(C):
    def show(self):
    super().show()
    print('Dshow')
    # return 0
    def obj(obj):
    obj.show()
    # print(obj.show())
    if __name__ == '__main__':
    test1 = B()
    test2 = D()
    obj(test1)
    obj(test2)

    注:在obj函数中,如果我们用的是print,那么它打印出来的不仅仅是各类中show()函数中的执行方法,还有其返回值,而各类中并无return,即D类中的

    retrun 0
    ,它默认返回一个None值,则执行结果除了执行各类中的语句外,还返回了一个None值。如果不想有None值的返回,则直接调用方法即可,即
    obj.show()

    总结

    • 创建出来的对象叫做类的实例
    • 创建对象的动作叫做实例化
    • 对象的属性叫做实例属性
    • 对象调用的方法叫做实例方法
    • 对象各自拥有自己的实例属性
    • 调用对象方法,可以通过self访问自己的属性,以及调用自己的方法
    def x():
    self.xx()
    def xx():
    pass
    • python 中一切皆为对象,比如类也是对象
    • 类对象也有自己的属性和方法
    class Person:
    country = 'China' # 类属性
    def __init__(self,name):
    # 实例方法
    self.name = name #实例属性
    
    if __name__ == '__main__':
    xm = Person('小埋')
    print(xm.country) # 通过实例对象访问类属性
    print(Person.country) # 通过类本身访问类属性
    print(xm.name) # 通过对象访问实例属性
    # print(Person.name) # type object 'Person' has no attribute 'name',类对象不能访问实例属性
    
    xm.country = 'USA' # 通过实例对象修改类属性
    print(xm.country) # 实例属性修改了
    print(Person.country) # 类属性没有被修改
    
    Person.country = 'UK' # 通过类修改类属性
    print(Person.country) # 类属性被修改了
    print(xm.country) # 如果是类属性修改前创建的修仙,属性不会被修改
    
    xx = Person('HAHAHA')
    print(xx.country)
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: