目录
继承
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
##定义
class 派生类名(基类名)
...
继承特性
继承最大的好处是子类获得了父类的全部变量和方法的同时,又可以根据需要进行修改、拓展。
一,子类拥有父类非私有化的属性和方法。
二,子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
class Animal:
def eat(self):
print("eating...")
def sleep(self):
print("sleep...")
##继承类
class Dog(Animal):
def swimming(self):
print("toshetou...")
class Cat(Animal):
def climb_tree(self):
print("climb_tree...")
alex = Dog()
alex.eat()##继承父类方法
三,子类可以用自己的方式实现父类的方法(扩展父类方法)。super关键字调用父类方法(在子类方法定义中)
调用父类方法:
1. 父类对象调用: 父类对象.方法(self,其他参数)## Person.sleep(self)
2. super关键字: super(子类对象,self).方法(参数)或者 super( ). 父类方法( )
可在定义或调用时使用super()代表父类对象。
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def sleep(self):
print("基类sleep...")
class Emp(Person):
#重写父类对象属性
# def __init__(self,name,age,dep):
# self.name = name
# self.age = age
# self.dep = dep
def __init__(self, name, age, dep):
super().__init__(name,age) # 扩展父类对象属性
self.dep = dep # 扩展属性
def sleep1(self):
if "不在公司":
# print("子类sleep...")
# 调用父类方法
# 方式1 :父类对象调用 父类对象.方法(self,其他参数)
# Person.sleep(self)
# 方式2: super关键字 super(子类对象,self).方法(参数)or super().方法(参数)
super().sleep()
yuan = Emp("yuan",18,"教学部")
yuan.sleep1()
print(yuan.dep)
多重继承
如果在继承元组中列了一个以上的类,那么它就被称作"多重继承" 。派生类的声明,与他们的父类类似,继承的基类列表跟在类名之后,如下所示:
class SubClassName (ParentClass1[, ParentClass2, ...]):
...
class Animal:
def eat(self):
print("eating...")
def sleep(self):
print("sleep...")
class Fly:
def fly(self):
print("fly...")
class Eagle(Animal):
def fly(self):
print("fly...")
class Bat(Animal):
def fly(self):
print("fly...")
##添加一个公共类,并继承
class Fly:
def fly(self):
print("fly...")
class Eagle(Animal,Fly):
pass
class Bat(Animal,Fly):
pass
封装
封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
我们程序设计追求“高内聚,低耦合”:
高内聚:类的内部数据操作细节自己完成,不允许外部干涉
低耦合:仅对外暴露少量的方法用于使用。
私有属性
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
,在Python中,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
class Student(object):
def __init__(self, name, score):
self.name = name
self.__score = score##封装属性
alvin = Student("alvin",66)
yuan = Student("yuan",88)
print(alvin.__score)
##输出失败
改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__score
。
获取和更改封装属性
外部代码要获取score怎么办?可以给Student类增加
get_score
这样的方法:允许外部代码修改score怎么办?可以再给Student类增加
set_score
方法:get加封装变量,set加封装变量
class Student(object):
def __init__(self, name, score):
self.name = name
self.__score = score
def get_score(self):
return self.__score ##方法内返回封装的属性
def set_score(self,score):
self.__score = score
alvin=Student("alvin",66)
yuan=Student("yuan",88)
alvin=Student("alvin",12)
print(alvin.get_score()) ##调用对象get方法获取属性
alvin.set_score(100) ##调用set方法
print(alvin.get_score())##输出get方法获取的属性
单下划线、双下划线、头尾双下划线说明:
-
__foo__
: 头尾双下划线,定义的是内置方法,一般是系统定义名字 ,类似__init__()
之类 -
_foo
: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问。(约定成俗,不限语法)get方法名和set方法名后接_foo属性 -
__foo
: 双下划线的表示的是私有类型(private)的变量,(可以是私有方法名和属性名前缀) 只能是允许这个类本身进行访问了。
私有方法
在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的:
class Base:
def __foo(self): ##__foo私有化方法定义
print("foo from Base")
def test(self):##普通对象方法
self.__foo()
class Son(Base):
def __foo(self):
print("foo from Son")
s=Son()
s.test()
##结果:foo from Base
##继承方法和属性为父类的
多态
多态存在的三个必要条件:
继承,重写,父类引用指向子类对象
狗、猫、猪都继承了动物类,并各自重写了kind方法。show_kind()函数接收一个animal参数,并调用它的kind方法。可以看出,无论我们给animal传递的是狗、猫还是猪,都能正确的调用相应的方法,打印对应的信息。这就是多态。 同一函数具有不同返回值,实现前提是继承和重写父类方法。
class Animal():
def show_kind(self):
print('i am animal')
class Dog(Animal):
def show_kind(self):
print('i am dog')
class Cat(Animal):
def show_kind(self):
print('i am cat')
class Car():
def show_kind(self):
print('i am car')
def Give(a):
a.show_kind()
cat = Cat()
dog = Dog()
car = Car()
Give(car)
python的接口类和抽象类
在Python中定义一个接口类,我们需要abc模块
(抽象类基类,Abstract Base Classes)中的两个工具abstractmethod, ABCMeta,详情如下:
工具 | 说明 |
---|---|
abstractmethod | 抽象类的装饰器,接口类中的接口需要使用此装饰器 |
ABCMeta | 抽象类元类 |
from abc import ABCMeta, abstractmethod # (抽象方法)
# metaclass 元类 metaclass = ABCMeta表示Payment类是一个规范类
class Payment(metaclass=ABCMeta):
def __init__(self, name, money):
self.money = money
self.name = name
# @abstractmethod表示下面一行中的pay方法是一个必须在子类中实现的方法
@abstractmethod
def pay(self, *args, **kwargs):
pass
class AliPay(Payment):
def pay(self):
# 支付宝提供了一个网络上的联系渠道
print('%s通过支付宝消费了%s元' % (self.name, self.money))
class WeChatPay(Payment):
def pay(self):
# 微信提供了一个网络上的联系渠道
print('%s通过微信消费了%s元' % (self.name, self.money))
class Order(object):
@staticmethod
def account(pay_obj):
pay_obj.pay()
pay1 = WeChatPay("yuan", 100)
pay2 = AliPay("alvin", 200)
order = Order()
order.account(pay1)
order.account(pay1)