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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值