我们知道:类有三个特征:封装、继承、多态。
1. 类的封装
封装:类封装了一些方法,可通过一定的规则约定方法进行访问权限。
封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用用者只知道一个接口(函数),可以通过这个接口去实现类内部写好的功能,但是不能直接访问或者修改类中的私有变量。
在python中,默认的成员变量都是public的,如果成员变量前面是加两个下划线,表示该成员变量是私有的。并且private类不能被继承类引用,并且不允许直接访问。
class People():
#类的初始化方法
def __init__(self,name,age):
#私有变量
self.__name=name
self.age=age
#类中定义的函数
def print_self(self):
print(self,self.__class__)
def getname(self):
return self.__name
#类的实例
a1=People("zhangsan",20)
#使用点号 . 来访问对象的属性
print(a1.age)
#访问私有变量,报错
print(a1.__name)
#通过类中的函数将私有变量返回
print(a1.getname())
2. 类的继承
继承让我们能够创建两个或多个类之间的“是一个”的关系。(例如,猫是一个动物)将共有的逻辑抽象到基类中,并在子类中控制具体的细节。
通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。通过继承,子类可以获得父类的全部属性及功能。
(1) 基本的继承:
- 其实,我们创建的所有类都使用了继承关系。所有的python类都继承一种特殊的类——object类。object类只提供很少量的数据和行为。如果我们不明确继承的类,就会自动的继承object类。
- 我们在继承父类的时候,只要将父类的名字放进类名后及冒号之前的括号内即可,这样我们就可以告诉子类所继承的父类。
实例1:
在下面这个简单的例子中,当我们实例化Child的时候,子类继承了父类的构造函数,就需要提供父类Person要求的两个属性变量 name 和age。
class People():
#类的初始化方法
def __init__(self,name,age):
#私有变量
self.name=name
self.age=age
#类中定义的函数
def print_self(self):
print(self,self.__class__)
#继承People类
class Child(People):
pass
a1=People("zhangsan",20)
a2=Child("lisi",21)
print(a1.age, a1.name)
a1.print_self()
#子类继承父类的属性和方法
print(a2.age,a2.name)
a2.print_self()
结果如下:
20 zhangsan
<__main__.People object at 0x000000000257B278> <class '__main__.People'>
21 lisi
<__main__.Child object at 0x000000000257B2B0> <class '__main__.Child'>
(2)重写方法:
在继承关系中,很适合向已经存在的类中添加新的行为和修改某些行为。这就需要我们去重写某些方法。重写意味着在子类中修改或者替换基类中原有的方法(采用相同的函数名),当调用函数时,新创建的子类的方法将会被自动调用。
实例1:
将父类的myMethod方法进行重写,执行子类的myMethod方法。
class Parent: # 定义父类
def myMethod(self):
print('Parent')
class Child(Parent): # 定义子类
def myMethod(self):
print('Child')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
结果如下:
Child
实例2:
1. 这个实例定义了两个类,一个类是Ticket类,另一个类是GaoTie类;GaoTie类继承Ticket类;
2. 在Ticket类中初始化了六个参数,分别为车站名,出发站,到达站,出发时间,到达时间,和无座;
3. 在GaoTie类中重写了父类的初始化方法和display方法;
from prettytable import PrettyTable
#父类
class Ticket():
#初始化六个参数
def __init__(self, from_station, to_station, from_t, to_t, id, wu):
self.id = id
self.from_station = from_station
self.to_station = to_station
self.from_t = from_t
self.to_t = to_t
self.wu = wu
def display(self):
#prettytable表格化输出结果
ptable = PrettyTable("车次 出发站 到达站 出发时间 到达时间 无座".split())
ptable.add_row([self.id, self.from_station, self.to_station, self.from_t, self.to_t, self.wu])
print(ptable)
#继承Ticket类,子类,继承有什么好处?最大的好处是子类获得了父类的全部属性及功能
class GaoTie(Ticket):
#重写初始化的方法,只需要添加需要的内容即可
def __init__(self, from_station, to_station, from_t, to_t, id, yideng, erdeng, wu):
Ticket.__init__(self, from_station, to_station, from_t, to_t, id, wu)
self.yideng = yideng
self.erdeng = erdeng
#重写了父类的方法
def display(self):
ptable = PrettyTable("车次 出发站 到达站 出发时间 到达时间 一等座 二等座 无座".split())
ptable.add_row([self.id, self.from_station, self.to_station, self.from_t, self.to_t, self.yideng, self.erdeng, self.wu])
print(ptable)
#创建类的实例
print("普通车:")
t = Ticket("西安", "北京", "10:00", "15:00", "T33", 1)
t.display()
print("高铁:")
g = GaoTie("西安", "上海", "10:00", "15:00", "G44", 4, 5, 6)
g.display()
结果如下:
(3)多重继承:
多重继承的原则非常的简单:子类继承多个父类,同时可以获取所有父类的功能。但是在实践中,不建议这样使用。
class A():
def myMethod(self):
print("A----->mymethod")
class B():
def myMethod(self):
print("B----->mymethod")
#多重继承
class C(B,A):
pass
#当子类继承多个父类的时候,按括号中继承父类的先后顺序,所有,打印B----->mymethod
c=C()
c.myMethod()
结果如下:
B----->mymethod
(4) isinstance() 和 issubclass():
isinstance() 用于检查实例类型;判断一个对象是类的实例,语法:isinstance(实例,类)
issubclass() 用于检查类继承;判断一个类是另一个类的子类或者子孙类,语法:issubclass(子类,父类)
如下实例:在继承关系中,如果一个实例的数据类型是某个子类,那它也可以被看做是父类(a2 既是 Child 又是 Person的对象)。但是,反过来就不行(a1 仅是 Person,而不是Child的对象)。
class People():
#类的初始化方法
def __init__(self,name,age):
self.name=name
self.age=age
#继承People类
class Child(People):
pass
a1=People("zhangsan",20)
a2=Child("lisi",21)
print(a1.age, a1.name)
#子类继承父类的属性和方法
print(a2.age,a2.name)
通过上面那个例子,我们可以得到:
issubclass(Child,People)——————>True
isinstance(a2, Child)——————>True
isinstance(a2, People)——————>True
isinstance(a1, People)——————>True
isinstance(a1, Child)——————>False
3. 类的多态
多态:当子类和父类都存在相同的方法时,我们说,子类的方法覆盖了父类的方法,在代码运行的时候,总是会调用子类的方法。这样,我们就获得了继承的另一个好处:多态(一对多)。
class Parent: # 定义父类
def __init__(self,name):
self.name=name
def myMethod(self):
print('Parent--->',self.name)
class Child(Parent): # 定义子类
def myMethod(self):
print('Child--->',self.name)
class Man(Parent): # 定义子类
def Method(self):
print('Man--->',self.name)
c = Child('zhangsan') # 子类实例
c.myMethod() # 子类调用重写方法
m=Man('lisi') # 子类实例
m.myMethod() # 子类调用父类的方法,不重写函数
结果如下:
Child zhangsan
Parent lisi