python入门超easy系列(八)——— 面向对象之封装、继承与多态

了解面向对象三大特点,在项目中Be a Boss?

众所周知,python是世界上入门最简单的语言!?——周某人


面向对象的三大特点

  • 封装:既是对数据结构的封装,又是处理数据的方法的封装。
  • 继承:强调的是父子类的关系
  • 多态:不同对象调用相同的方法,有不同的响应。

下面将仔细对这三大特点进行详细阐述和实例演示


类的封装

我们在创建类的时候,class里面包裹着类的属性和方法其实就是对类的封装机制(emmmmmm,不知道这样大家能不能理解)


类的继承

  • 相关概念:

    • 定义:父类的属性和方法,子类可以直接拥有,称为继承。
    • 派生:子类在父类的基础上衍生出新的特征(属性或行为),称为派生。
    • 总结:其实他们是一回事,知识描述问题的角度不同(继承侧重相同点,派生侧重不同点)
  • 继承语法:父类拥有属性和方法的子类都能直接拥有

    # 当没有写父类时,默认继承自object
    class Animal(object):
        def __init__(self, name):
            self.name = name
    
        def run(self):
            print('小动物喜欢一天到晚跑个不停')
            
    # 定义一个子类,继承自Animal  
    class Dog(Animal):
        pass
    
    d = Dog('旺财')
    # 可以直接拥有父类的属性
    print(d.name)
    # 也拥有父类的行为
    d.run()
    
  • 派生示例:子类可以派生出父类没有的方法和属性

    class Animal:
        def run(self):
            print('一天到晚跑个不停')
    
    class Cat(Animal):
        def eat(self):
            print('猫喜欢吃鱼')
    
    c = Cat()
    c.run()
    
    # 添加的属性
    c.name = '加菲'
    
    print(c.name)
    # 派生的方法
    c.eat()
    
  • 方法重写:父类中的方法不适合子类,可以将其覆盖重写

    class Animal:
        def run(self):
            print('小动物喜欢到处跑')
    
        def eat(self):
            print('小动物喜欢吃东西')
            
    class Cat(Animal):
        # 父类方法完全不合适,覆盖重写
        def run(self):
            print('猫喜欢走猫步')
    
    	# 父类的方法不够完善,需要添加完善
    	def eat(self):
            # 保留父类方法的内容
            
            # Animal.eat(self)    # 不建议使用
            # super(Cat, self).eat()
            
            super().eat()           # 推荐使用
            # 添加完善的内容
            print('猫喜欢吃鱼')   
    
    c = Cat()
    c.eat()
    c.run()
    
  • 多继承:一个类可以有多个父类

    class A:
        def test(self):
            print('in class A  func test...')
            
    class B:
        def test(self):
            print('in class B  func test...')
    
        def eat(self):
            print('in class B func eat ...')   
            
    class C(A, B):
        def eat(self):
            # 默认的方式找父类,跟不重写方法时的顺序是一样的,
            # 按照书写的先后顺序,默认是写在前面的类的方法
            # super().eat()
            # 明确指定调用哪个父类的方法
            B.eat(self)
    
    c = C()
    c.test()
    c.eat()        
    

类的多态

  • 定义:不同的对象,调用相同的方法,会有不同的响应,大概意思就是 “ 猫吃鱼狗吃肉 ” 酱紫

  • 具体示例:

    class Animal:
    	def run(self):
    		print('小动物走道都不一样')
    
    class Cat(Animal):
        def run(self):
            print('猫都的是猫步')
            
    class Dog(Animal):
        def run(self):
            print('狗一般都走S型')
            
    def func(obj):
        obj.run()
     
    # 这里的代码,大家动一下脑筋
    func(Cat())
    func(Dog())
    

权限管理

  • 私有属性/方法:在一个类里面,例如用户类,我们希望我们的密码不能被外部使用或者直接访问,此时我们就可以将该属性设置为私有属性。

  • 设置方法:两个下划线开头,声明该属性为私有

  • 具体示例:(示例内包含一些重要内容,不知道怎么说,看代码吧)

    class Person:
          def __init__(self, name, age):
              self.name = name
              # 定义私有属性
              self.__age = age
    
          def test(self):
              # 私有属性和方法可以在类的内部使用
              print(self.__age)
              self.__hello()
              
          # 定义私有方法
          def __hello(self):
              print('for test')
              
    class Man(Person):
    	def show(self):
          	# 私有属性和方法在子类也不可以使用
          	print(self.__age)
            
    p = Person('老王', 38)
    print(p.name)
    # 属性前添加连个下划线,类的外部不能使用
    # print(p.__age)
    
    # 默认在添加两个下划线的属性名前添加了'_类名'
    # print(p.dict)
    # 强烈建议不要这样使用
    # print(p._Person__age)
    
    p.test()
    # p.__hello()
    m = Man('小明', 18)
    # m.show()
    

类属性

  • 类属性:属于整个类

  • __slots__:限制对象可以使用的属性,可以提高效率,节约存储空间

  • 具体示例:

    class Person:
        # nation = '中国'
    
        __slots__ = ('name', 'age', 'nation')
    
        def __init__(self, name):
            # 成员属性,属于某个对象
            self.name = name
            # 成员属性,当不存在会会试着找一下类属性
            # self.nation = 'xxx'
    
        def test(self):
            pass
    
    # 通过类名访问类属性
    # print(Person.nation)
    
    p = Person('王大花')
    # 可以通过对象访问类属性,但是不建议
    print(p.name)
    # print(p.nation)
    
    p.age = 20
    # p.height = 180
    
    # 特殊的类属性
    # 类名字符串
    print(Person.__name__)
    
    # 父类组成的元组,大家可以尝试让该类继承多个父类,查看输出结果
    print(Person.__bases__)
    
    # 类相关的信息
    print(Person.__dict__)
    
    print(Person.__slots__)
    

类方法

  • 说明:

    • 通过类名进行调用
    • 定义是需要使用装饰器classmethod
  • 作用:

    • 可以创建对象或者简洁的创建对象
    • 可以对外提供简易的接口
  • 示例一:

    class Person:
        # 成员方法,通过对象进行调用
        def eat(self):
            print('红烧鸡腿我喜欢吃')
    
    	# 类方法,通过类名进行调用
        @classmethod
        def test(cls):
            # cls表示当前类
            print(cls, '类方法')
    
      	# 创建对象
        @classmethod
        def create(cls):
            obj = cls()
            obj.age = 1
            return obj     
         
    p = Person()
    p.eat()
    Person.test()
    # 创建或者简洁的创建对象  
    p2 = Person.create()
    print(type(p2))
    
  • 示例二: 计算3^2 + 4^2

    class Number:
          def __init__(self, num1, num2):
              self.num1 = num1
              self.num2 = num2
    
          def add(self):
              return self.num1 + self.num2
    
          def sub(self):
              return self.num1 - self.num2
    
          def mul(self):
              return self.num1 * self.num2
    
          def div(self):
              if self.num2 == 0:
                  return None
              return self.num1 / self.num2
    
          # 对外提供简单易用的接口
          @classmethod
          def pingfanghe(cls, num1, num2):
              n1 = cls(num1, num1)
              n12 = n1.mul()
              n2 = cls(num2, num2)
              n22 = n2.mul()
              n3 = cls(n12, n22)
              return n3.add()
    
    # 计算3^2 + 4^2
    # n1 = Number(3, 3)
    # n12 = n1.mul()
    #
    # n2 = Number(4, 4)
    # n22 = n2.mul()
    #
    # n3 = Number(n12, n22)
    # ret = n3.add()
    # print(ret)
    
    print(Number.pingfanghe(3, 4))
    
  • 小总结:类方法是一种通过创建自身对象来调用自身方法的特殊方法。(这样说你们晕不晕?)


静态方法

  • 说明:

    • 通过装饰器staticmethod修饰
    • 通过类名进行调用
  • 示例:

    class Person:
          # 静态方法:没有cls参数
          @staticmethod
          def test():
              print('static method test ...')
    
          # 静态方法:可以创建对象
          @staticmethod
          def create():
              p = Person()
              p.age = 1
              return p
          
    Person.test()
    p = Person.create()
    print(type(p))  
    
  • 小总结:

    • 凡是静态方法能够解决的问题类方法都能解决
    • 若方法中没有涉及类名的操作,可以使用静态方法代替类方法

属性函数

  • 说明:可以将成员方法当作属性一样访问

  • 作用:获取时以及设置指定属性时都可以进行人为干预,可以保护特定属性,比如说用户类中的密码

  • 示例:

    class User:
        def __init__(self, username, password):
            self.username = username
            self.__password = password
    
        # 可以将方法像访问属性一样访问
        @property
        def test(self):
            return 'hello'
    
        # 保护指定的属性
        @property
        def password(self):
            print('大哥,有人想偷看密码')
            return '哈哈,让你偷看,没门'
    
        # 在设置对应属性时会自动调用
        @password.setter
        def password(self, password):
            print('密码设置', password)
            # 人为干预密码的设置过程,如:加密存储密码
            self.__password = 'xxx' + password + 'yyy'
            
    u = User('大狗', '123456')
    # u.test()
    # print(u.test)
    print(u.password)
    u.password = '654321'
    print(u.__dict__)
    

抽象基类(了解)

  • 说明:

    • 抽象基类就是为了统一接口而存在的
    • 抽象类不能进行实例化(创建对象)
    • 继承自抽象类的子类必须实现抽象类中的抽象方法
  • 示例:

    from abc import ABC, abstractmethod
    
    # 抽象基类
    class Animal(ABC):
        # 定义抽象方法:规定接口
        @abstractmethod
        def run(self):
            pass     
        
        
    # 抽象基类无法实例化  
    # a = Animal()
    class Cat(Animal):
        # 子类中必须实现抽象基类的抽象方法,才能实例化
        def run(self):
            print('猫喜欢走猫步')   
            
    c = Cat()           
    

总结

今天的内容超级多,大概花最多两天的时间可以消化,自己根据每个知识点自己想象一些好玩的例子,用代码写出来。还有就是,代码中有很多很多注释掉的代码,需要大家由上至下依次取消注释来运行代码,加深理解。内容比较多,所以很多隐藏知识点都在代码里面呢。


下期预告:下一期篇幅比较短,用来介绍python中的错误和异常处理
Tips:如有疑问欢迎随时打扰 ???

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值