python语法--面向对象基础(19)

1.初识面向对象

1.1 面向过程

面向过程:根据业务逻辑从上到下写代码。开发过程的思路是将数据与函数按照执行的逻辑顺序组织在一起,数据与函数分开考虑,面向过程基本是由函数组成的。

特点:
注重步骤与过程,不注重职责分工
如果需求复杂,代码会变得很复杂
开发复杂项目,没有固定的套路,开发难度很大!

1.2 面向对象

特点:
注重 对象和职责,不同的对象承担不同的职责。
更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路。
需要在面向过程基础上,再学习一些面向对象的语法。

2. 类和对象

2.1 类

类是对一群具有相同特征或者行为 的事物的一个统称,是抽象的,不能直接使用。类里包括属性和方法。所谓属性就是该类的特征,而方法就是该类可以执行的动作。

类的定义:

       class 类名:   类名首字母大写

2.1.1 属性

python支持动态添加属性,谁创建对象,self就指向谁。属性可以是系统类型,也可以是自定义的类型。

类属性:直接在该类下定义的属性,即 变量名 = 值。
设置类属性:类名.属性名 = 值, 如果有该属性就修改,没有就新建该属性。
只要修改类属性,其余为未修改对象属性的对象的该属性都将改变。
类属性可以通过类对象和实例对象访问。

尽量避免类属性和实例属性同名。如果有同名实例属性,实例对象会优先访问实例属性。
类属性只能通过类对象修改,不能通过实例对象修改。
类属性也可以设置为私有,前边添加两个下划线。

对象属性:
设置对象属性:对象名.属性名 = 值, 如果有该属性就修改,没有就报错。
只要一经修改对象属性,无论类属性如何改变,该对象的该属性都不会改变。
上述方法给对象添加属性,可能会出现问题。所以引入__init__方法.

私有属性只能在类体内部使用或者调用各种方法才能使用,外界不能直接通过 对象名。属性名 来使用。格式为,__属性名,python将私有属性改名为_类名__属性名来隐藏该属性,使外界无法访问。也可以通过 对象名._类名__属性名来访问私有属性,但是强烈不建议这样使用。

2.1.2 方法

哪个对象调用了方法,方法里的self指的就是谁。 通过 self.属性名 可以访问到这个对象的属性;通过 self.方法名() 可以调用这个对象的方法。

对象方法:只能通过对象来调用

类方法: 对象方法上加@classmethod装饰器,将self改为cls。

             调用:  类名。方法名()
                    对象名。方法名()

静态方法:对象方法上加@staticmethod装饰器,无需加self、cls。不依赖类

调用:

              类名。方法名()
              对象名。方法名()

2.2 对象

对象是由类创建出来的一个具体存在,可以直接使用属性名。由哪一个类创建出来的 对象,就拥有在哪一个类中定义的属性和方法。只要创建对象,就为其分配一个内存空间。

创建对象的语法:

          对象变量名 = 类名()

使用dir函数查看对象的所有方法:

格式:

           print(dir(对象名))

2.3 类和对象的关系

类是模板,对象是根据类这个模板创建出来的,应该先有类,再有对象。
使用同一个类,能够创建出很多对象。
类中定义了什么属性和方法,对象中就有什么属性和方法。
不同对象对应的属性值也会不同。

3. 魔法方法

3.1 __init__方法

init()方法,在创建一个对象时默认被调用,不需要手动调用。在开发中,如果希望在创建对象的同时,就设置对象的属性,可以对 init 方法进行改造。

注意:

__init__()方法在创建对象时,会默认被调用,不需要手动的调用这个方法。
__init__()方法里的self参数,在创建对象时不需要传递参数,python解释器会把创建好  的对象引用直接赋值给self
在类的内部,可以使用self来使用属性和调用方法;在类的外部,需要使用对象名来使用属性和调用方法。
如果有多个对象,每个对象的属性是各自保存的,都有各自独立的地址。
方法是所有对象共享的,只占用一份内存空间,方法被调用时会通过self来判断是哪个   对象调用了实例方法。

3.2__ str__方法

__str__方法返回对象的描述信息,使用print()函数打印对象时,其实调用的就是这个对象的__str__方法。

3.3 __del__方法

当删除对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法。

3.4__ new__方法

创建对象时调用该魔法方法,先于init调用。它在内存申请了一个空间,供对象使用。

3.5__mro__方法

主要用于在多继承时判断方法属性的调用顺序。

new、init的区别:

 new方法需要一个返回值,返回创建的实例对象,init不需要返回值
 new负责对象的创建,而init负责对象的初始化
new创建对象时调用,会返回当前对象的一个实例,而init是创建完对象后调用,对当前对象进行初始化
在类中new,init同时存在优先调用new
如果__new__返回一个对象的实例,会隐式调用__init__

4.面向对象的特点

4.1 封装

私有属性,通过定义共有的set和get方法来获取和修改私有属性,为封装。

通过@property实现封装:

可以简化对象属性的获取和赋值,通过 对象名。属性获取属性值,通过对象名。属性 = 新值 来设置属性。

封装步骤:

          @property
          def 属性名(self):
                  return self.__xxx

          获取私有属性值: 对象名.属性 = 值
         
          @属性名.setter
          def 属性名(self,yyy):
                  if  条件:
                       self.__xxx = yyy
                  else:
                        代码块
                        
          修改私有属性:对象名.属性名 = 新值

4.2 继承

继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。继承描述的是多个类之间的所属关系。

子类只能继承父类非私有的属性和方法

当子类和父类有相同的方法或者属性,优先使用子类自己的。

在子类里一个方法调用了另一个方法,而此方法在子类和父类中都有,优先调用子类的方法。如果要使用父类的方法,使用super().方法名()。

继承的传递性:子类拥有父类以及父类的父类中封装的所有属性和方法。

重写:当父类中的方法不能满足子类的需求,需要自己定义一个与父类同名的方法。当调用该方法时,优先调用子类的方法。如果要使用父类的方法,使用super(子类名,self).父类方法名()。

子类要新加属性时,需要重新声明父类的属性,格式如下

  class Worker(Person):
          def __init__(self,id,name,salary,hours,money):
                       super(Worker,self).__init__(id,name,salary)
                       self.hours = hours
                       self.money = money

语法:

                class 类名(父类名):
                       pass

多继承

格式:

           class 子类名(父类名1,父类名2...)
                  pass

注意:

当多个父类中有同名的方法或者属性,使用该方法或者属性时优先使用先传入的父类,所以应该避免使用多继承。

可以使用__mro__查看在多继承时方法属性的调用顺序。

                 print(类名.__mro__)

新式类:继承object,python3.x都是新式类,优先使用广度优先搜索

4.3 多态

不同的子类调用相同的父类方法,产生不同的执行结果,可以增加代码的外部灵活度。多态是以继承和重写父类方法为前提的,它是一种调用方法的技巧,不会影响到类的内部设计。

5.练习

在这里插入图片描述

class Pet:
    type = '宠物'

    def __init__(self, name, age, color):
        self.name = name
        self.age = age
        self.color = color

    def __str__(self):
        return '当前类型是{},宠物名{}'.format(self.type, self.name)


class Dog(Pet):
    type = '狗'

    def see_home(self):
        print('我能看家')


class Cat(Pet):
    type = '猫'

    def catch_mouse(self):
        print('我能抓老鼠')


class Petshop:

    def __init__(self, name):
        self.name = name
        self.petlist = []

    def add_pet(self, pet):
        if isinstance(pet, Pet):
            self.petlist.append(pet)
            print('宠物添加成功')
        else:
            print('不是宠物,无法添加。')

    def sale_pet(self, pet):
        if isinstance(pet,Pet):
            self.petlist.remove(pet)
            print('宠物卖成功')
        else:
            print('不能卖非宠物')

    def show_all(self):
        print('宠物商店宠物信息:')
        for pet in self.petlist:
            print(pet)

    def search_pet(self, pname):
        for pet in self.petlist:
            if pet.name == pname:
                print('宠物在商店中')
                break
        else:
            print('不存在该宠物!')



p = Petshop('华联宠物商店')


c = Cat('mao', 2, '白色')
d = Dog('gou',5,'黄色')
p.add_pet(c)
p.add_pet(d)
p.sale_pet(c)
p.show_all()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值