- 封装:既是对数据的封装,又是对处理数据方法的封装。
- 继承:强调父子类的关系
- 多态:不同的对象调用相同的方法,有不同的响应
类的继承
- 相关概念
- 继承:父类的属性和方法,子类直接拥有,称为继承。
- 派生:子类在父类的基础上衍生出的新的特征(属性和行为)。
- 总结:其实他们是一回事,只是描述问题的侧重点不同(继承侧重相同点,派生侧重不同点)
- 继承与派生
- 继承
# class Animal: # 当没有写父类时,默认继承自object类 class Animal(object): def __init__(self, name): self.name = name def run(self): print('很多小动物喜欢到处奔跑') 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.eat() # 动态添加的属性 c.name = '加菲' print(c.name)
- 方法重写
class Animal: def eat(self): print('小动物一天到晚吃个不停') def run(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.run() c.eat()
- 多继承:一个类可以有多个父类
- 基本语法
class A: def eat(self): print('eat func in class A') class B: def run(self): print('run func in class B') def eat(self): print('eat func in class B') # 多继承,多个父类之间使用逗号隔开 class C(A, B): def eat(self): # 不重写或直接使用super,都是采用的默认继承顺序 # super().eat() # 明确指定调用哪个父类的方法 B.eat(self) c = C() c.eat() c.run()
- 继承链的顺序
class A(object): def foo(self): print('A foo') class B(object): def foo(self): print('B foo') def bar(self): print('B bar') class C1(A, B): pass class C2(A, B): def bar(self): print('C2-bar') class D(C1, C2): pass d = D() d.foo() d.bar() # __mro__类属性,记录了继承连的查找顺序 # 一旦找到,立即停止并返回 # 采用的是广度优先遍历的原则 for i in D.__mro__: print(i)
- 访问权限
class Person: def __init__(self, name, age): self.name = name self.age = age self.__money = 100 def test(self): print('for test', self.__money) p = Person('王大花', 18) # 公有属性:在类内、类外以及子类中都可以使用 print(p.name) # 私有属性:只能在类的内部使用,类外及子类中都不能使用 # print(p.__money) p.test() print(p.__dict__) # 实现:在原有的属性名之前添加了'_类名'的前缀 # 不建议这样使用 # print(p._Person__money) class Man(Person): def introduce(self): print(self.name, self.age) # print(self.__money) m = Man('二狗', 20) print(m.name) m.test()
- 总结:
- 公有属性:在类的内部、外部、子类中都可以使用
- 私有属性:只能在类的内部使用,不能在外部及子类中使用
- 实现原理:默认在以
__
开头的属性前添加了_类名
的前缀
- 类属性
class Person: # 类属性:通过类名进行访问 nation = '中国' # 限制对象可以使用的属性,可以大幅提升访问的效率 __slots__ = ('name', 'age') def __init__(self, name): self.name = name xiaoming = Person('小明') xiaohong = Person('小红') print(xiaoming.name) print(xiaohong.name) # 访问类属性,通过类名访问 print(Person.nation) # 不要这样使用 # print(xiaoming.nation) # 查看对象的类型 print(xiaoming.class) # 特殊的类属性 # 类的名字 print(Person.__name__) # 父类组成的元组 print(Person.__bases__) # 类相关的信息 print(Person.__dict__) # 继承链查找顺序 print(Person.__mro__) # print(Person.slots) # 不能添加,因为slots中没有改属性 # xiaoming.weight = 180
- 类方法
- 说明:也是通过类名调用,创建时需要使用装饰器
classmethod
- 创建对象或简单的创建对象
class Person: # 成员方法,通过对象调用 def eat(self): print('能吃是福') # 类方法,通过类名调用 def test(cls): # cls表示当前类 print(cls) # 创建对象 或 简单的创建对象 def create(cls): p = cls() p.age = 1 return p p = Person() p.eat() Person.test() p2 = Person.create() print(p2.age, type(p2))
- 说明:也是通过类名调用,创建时需要使用装饰器
- 提供简洁易用的对外接口
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 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() # 直接调用类方法 print(Number.pingfanghe(3, 4))
- 静态方法
- 说明:也是通过类型调用,使用装饰器
staticmethod
装饰 - 示例:
class Person: # 定义静态方法 def test(): print('for test') # 可以创建对象 def create(): p = Person() return p class Man(Person): def test(): # 无法调用父类的方法 # super().test() print('xxx') Person.test() p = Person.create() print(type(p)) Man.test()
- 说明:也是通过类型调用,使用装饰器
- 总结
- 凡是使用静态方法解决的问题都可以使用类方法进行解决
- 静态方法重写时无法调用父类的方法
- 静态方法中没有cls的参数
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~