面向对象(三)

面向对象

继承

继承让类与类之间产生了关系,有了这层关系,才有我们后续要说的多态。
继承的引入
我们先来定义一个动物类:

class Animal:
    def sleep(self):
        print('动物会睡觉')
    def run(self):
        print('动物会跑')
a=Animal()
a.sleep()

那如果现在我又想定义一个狗类呢?
我有三种思路:
1.直接在动物类上修改,可以添加上一些狗的独有功能。
但这样做的话修改起来会比较麻烦,而且还违反了ocp原则。
2.创建一个新的类(狗类)
这样子的话同样比较麻烦,我们需要大量的复制粘贴
3.直接从Animal类中继承他的属性和方法
在定义类的时候可以在类名后的括号中指定当前类的父类(超类,基类)

class Animal:
    def sleep(self):
        print('动物会睡觉')
    def run(self):
        print('动物会跑')
class Dog(Animal):
    pass
d=Dog()
d.run()

我们来看输出结果:
在这里插入图片描述
我们并没有在Dog类中定义run()方法,但是最后能够输出结果,说明了这个Dog类继承了Animal类,在Animal类中有run方法。
同样我们能在这个基础上定义狗所独有的功能,我们可以再定义一个方法:

class Animal:
    def sleep(self):
        print('动物会睡觉')
    def run(self):
        print('动物会跑')
class Dog(Animal):
    def speak(self):
        print('汪汪汪')
d=Dog()
d.run()
d.speak()

输出结果:
在这里插入图片描述
在创建类的时候,如果省略了父类,则默认父类为object。如class Animal(object):

issubclass(): 检查一个类是不是另外一个类的子类。
如我们在上面代码在加上一行

print(issubclass(Dog,Animal))

它的返回结果为True,Dog确实为Animal的子类。
我们来试试加上这几行代码:

class Animal:
    def sleep(self):
        print('动物会睡觉')
    def run(self):
        print('动物会跑')
class Dog(Animal):
    def speak(self):
        print('汪汪汪')
d=Dog()
d.run()
d.speak()
print(issubclass(Dog,Animal))
print(issubclass(Dog,object))
print(issubclass(Animal,object))
print(issubclass(int,object))
print(issubclass(Dog,int))

在这里插入图片描述
通过这可以看到object是所有类的父类。

方法的重写

如果在子类中有和父类重名的方法,则通过子类实例去调用该方法时会调用子类的方法,而不是父类中的方法。这个特点我们称之为方法的重写(覆盖)

class A(object):
    def test(self):
        print('A...')
class B(A):
    def test(self):
        print('B...')
class C(B):
    pass
c=C()
c.test()

在这里插入图片描述
如果A,B类中都没有test()方法,该程序就会报错。
如果B类中没有test()方法,则会输出A…

当我们调用一个对象的方法时
会优先去当前对象中寻找是否具有该方法,如果有则直接调用。
如果没有则去当前对象的父类中寻找,如果父类中有,则直接调用父类中的方法。
如果还没有,则去父类中的父类寻找,以此类推,直到找到object,如果依然没找到就报错。

super()

class Animal(object):
    def __init__(self,name,age,height):
        self._name=name
        self._age=age
        self._height=height
    @property
    def name(self):
        return self._name
    def age(self):
        return self._age
    @name.setter
    def name(self,name):
        self._name=name
    def age(self,age):
        self._age=age
class Dog(Animal):
    def __init__(self,name,age,height,weight):
        super().__init__(name,age,height)
        self._kanjia=weight
    @property
    def weight(self):
        return self._kanjia
    print('狗会看家')
    @weight.setter
    def kanjia(self,kanjia):
        self._kanjia=kanjia
d=Dog('小黄','3','3','3')
d.name='小奶狗'
print(d.name)

看上面这个例子,我们用了super()
在这个例子里我们定义了,name,age,height,weight这几个属性,使用super()这个方法,我们就直接在他后面加上父类有的属性,然后单独写子类独有的属性。假如我们不用super()方法,我们就得写上:

 self._name=name
 self._age=age
 self._height=height

这样写就比较复杂了,要是有很多属性,我们还得写很多这样的代码。所以使用super()方法就方便多了。

多重继承

在python中是支持多继承的,也就是我们可以为一个类指定多个父类,如果多个父类中出现同名的方法,则会先在第一个父类中寻找,然后是第二个…以此类推。

class A(object):
    def test1(self):
        print('A...')
class B(object):
    def test1(self):
        print('B中test1的方法')
    def test2(self):
        print('B...')
class C(A,B):
    pass
c=C()
c.test1()

就像这样现在第一个父类中寻找,第一个父类中有所以输出A…
在这里插入图片描述

多态的简介

多态是面向对象的三大特征之一

class A(object):
    def __init__(self,name):
        self._name=name
    @property
    def name(self):
        return self._name
    @name.setter
    def name(self,name):
        self._name=name
class B(object):
    def __init__(self,name):
        self._name=name
    @property
    def name(self):
        return self._name
    @name.setter
    def name(self,name):
        self._name=name
a=A('葫芦娃')
b=B('钢铁侠')
def speak(obj):
    print('好好复习%s'%obj.name)
speak(a)
speak(b)

在这里插入图片描述
现在我来把代码改成这样:

class A(object):
    def __init__(self,name):
        self._name=name
    @property
    def name(self):
        return self._name
    @name.setter
    def name(self,name):
        self._name=name
class B(object):
    def __init__(self,name):
        self._name=name
    @property
    def name(self):
        return self._name
    @name.setter
    def name(self,name):
        self._name=name
a=A('葫芦娃')
b=B('钢铁侠')
def speak(obj):
    if isinstance(obj,A):
        print('好好复习%s'%obj.name)
speak(b)

在这里插入图片描述
没有输出结果,这就违反了多态。
我们常见的一个==len()==函数体现的就是一种多态

lst=[1,2,3,4,5,6,7,8]
str='python'
print (len(lst))
print (len(str))

在这里插入图片描述
不管是什么类型,len()函数都能输出他们的长度。

面向对象的三大特性

  • 封装 :确保对象中的数据安全
  • 继承:保证了对象的可拓展性
  • 多态:保证了对象的灵活性**

属性和方法

类属性:直接在类中定义的属性
类属性可以通过类和该类的实例来访问

class A(object):
    count=0
a=A()
print(a.count)
print(A.count)

在这里插入图片描述
实例属性:通过实例来添加的属性就是实例属性
类中的属性只能通过类对象来修改,无法通过实例对象来修改
我们来看下面这两串代码

class A(object):
    count=0
a=A()
a.count=10
print(a.count)
print(A.count)

在这里插入图片描述
我们可以看到修改了实例属性为10,类属性还是0没有改变

class A(object):
    count=0
a=A()
a.count=10
A.count=20
print(a.count)
print(A.count)

在这里插入图片描述
我们可以看到只有通过修改类对象来修改类属性。


实例属性只能通过实例对象来访问,类对象无法访问和修改

class A(object):
    count=0
    def __init__(self):
        self.name='葫芦娃'
a=A()
print(a.name)

在这里插入图片描述

class A(object):
    count=0
    def __init__(self):
        self.name='葫芦娃'
a=A()
print(A.name)

报错了,类对象不能访问
在这里插入图片描述


当通过实例对象调用时,会自动传递当前对象作为self传入
当通过类去调用时,不会自动传递self

class A(object):
    count=0
    def __init__(self):
        self.name='葫芦娃'
    def test(self):
        print('这是一个test方法')
a=A()
a.test()

在这里插入图片描述
如果通过类调用呢?

class A(object):
    count=0
    def __init__(self):
        self.name='葫芦娃'
    def test(self):
        print('这是一个test方法')
a=A()
A.test()

报错
在这里插入图片描述
没有self这个参数,所以我们要怎么做呢

class A(object):
    count=0
    def __init__(self):
        self.name='葫芦娃'
    def test(self):
        print('这是一个test方法')
a=A()
A.test(a)

在这里插入图片描述
成功执行了。
实例方法可以通过类对象调用,也可以通过实例对象去调用。
a.test()等价于A.test(a)

**类方法:**在类的内部使用@classmethod来修饰的方法属于类方法,类方法的第一个参数我们习惯写成cls,cls就相当于当前的类对象

class A(object):
    count=0
    @classmethod
    def test(cls):
        print('这是一个test方法')
        print(cls.count)
a=A()
A.test()

在这里插入图片描述

class A(object):
    count=0
    @classmethod
    def test(cls):
        print('这是一个test方法')
        print(cls.count)
a=A()
a.test()

在这里插入图片描述
从上面可以看出类方法可以通过类对象调用,也可以通过实例对象来调用。
A.test()等价于a.test()

静态方法

在类中用@staticmethod来修饰的方法我们称之为静态方法。
不需要制定任何的默认参数,静态方法可以被类对象和实例对象来调用:

class A(object):
    count=0
    @staticmethod
    def test():
        print('这是一个test方法')
a=A()
A.test()
a.test()

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值