封装、继承和多态
面向对象有三大特性:封装、继承和多态
封装
-
封装是指将数据与具体操作的实现代码放在某个对象内部,使这些代码的实现细节不被外界发现且不能通过任何形式修改对象内部实现,正是由于封装机制。
- 打码平台示例代码:http://www.ttshitu.com/
-
作用:
继承
-
继承来源于现实世界:
-
在OOP程序设计中,当我们定义一个新类的时候,新的类称为子类(Subclass),而被继承的类称为基类、父类或超类(Base class、Super class)。
-
Python支持多父类的继承机制。
继承示例代码:
# 查看子类(学生)是否可以继承到父类(人)的属性和方法
class Person():
classVar = 'value'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def speak(self):
print('person can speak')
@classmethod
def classFunc(cls):
print('I am Person classFunc')
@staticmethod
def staticFunc():
print('I am Person staticFunc')
class Student(Person):
pass
s1 = Student('zhangsan',20,'F') # 子类可以继承父类的构造方法
print(s1.name,s1.age,s1.sex) # 子类可以继承父类的实例变量
print(Student.classVar) # 子类可以继承父类的类变量
s1.speak() # 子类可以继承父类的实例方法
Student.classFunc() # 子类可以继承父类的类方法和静态方法
Student.staticFunc()
派生
class Person():
classVar = 'value'
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def speak(self):
print('person can speak')
@classmethod
def classFunc(cls):
print('i am Person classFunc')
@staticmethod
def staticFunc():
print('i am Person staticFunc')
class Student(Person):
address = 'beijing' # 子类自己派生出来的类变量
# 如何让子类派生出自己独有的实例变量
def __init__(self,classNum,score,name,age,sex):
super().__init__(name,age,sex) # 调用父类的构造方法,作用从父类中继承过来实例变量
# classNum和score就是子类自己派生出来的实例变量
self.classNum = classNum
self.score = score
# 子类自己派生出来的方法
def learning(self):
pass
s1 = Student(3,100,'zhangsan',20,'sex') # 子类可以继承父类的构造方法
Student.classFunc() # 子类可以继承父类的类方法和静态方法
super通常是作用在子类的构造方法中,在子类的构造方法中通过super调用父类的构造方法,从而可以让子类继承到父类的实例变量
重写
思考:如果子类从父类中继承过来的方法,满足不了子类的应用,怎么办呢?
class Father():
def __init__(self,h):
self.h = h
def hobby(self):
return self.h
class Son(Father):
def __init__(self,h,a1,a2):
self.a1 = a1
self.a2 = a2
super().__init__(h)
def hobby(self):
#在继承父类原始方法操作的基础上新增添一些操作经即可
h_list = super().hobby()
h_list.append(self.a1)
h_list.append(self.a2)
return h_list
单继承
-
继承的作用:
-
实现了程序的高复用,大大缩短程序的开发周期!
-
算法补充
-
#:a+b+c=1000,a**2 + b**2 = c**2 for a in range(1001): for b in range(1001): c = 1000 - a - b if a+b+c == 1000 and a**2 + b**2 == c**2: print(a,b,c)
-
衡量算法性能好坏的方式:时间复杂度
-
排序算法:冒泡排序
-
1.乱序系列中的两两元素进行大小比较,将比较出较大的元素逐步向后偏移(序列中最大的值就已经偏移到最后了) # def sort(alist): # for i in range(len(alist)-1):#控制元素两两比较的次数 # if alist[i] > alist[i+1]: # alist[i],alist[i+1] = alist[i+1],alist[i] # return alist #2.将第一步的操作继续一次作用在前n个乱序的序列中 def sort(alist): for j in range(len(alist)-1): for i in range(len(alist)-1-j):#控制元素两两比较的次数 if alist[i] > alist[i+1]: alist[i],alist[i+1] = alist[i+1],alist[i] return alist alist = [3,8,5,7,6,2,1] print(sort(alist))
-
-
在多继承的时候要注意:
示例1:设想有下面的继承关系:
#B和E类中各自有一个相同的show方法,则A继承B和E后,直接调用show,则最终执行的show到底是B的还是E的?
class D():
pass
class C(D):
pass
class B(C):
def show(self):
print('B()->show')
class G():
pass
class F(G):
pass
class E(F):
def show(self):
print("E()->show")
class A(B,E):
pass
A().show()
so,在A的定义中,继承参数的书写有先后顺序,写在前面的被优先继承。
那如果B没有show方法,而是D有呢?
class D():
def show(self):
print('D()->show')
class C(D):
pass
class B(C):
pass
class G():
pass
class F(G):
pass
class E(F):
def show(self):
print("E()->show")
class A(B,E):
pass
A().show()
左边具有深度优先权,当一条路走到黑也没找到的时候,才换另一条路。
示例2:
那如果继承结构是这样的呢?类D和类G又同时继承了类H。当只有B和E有show方法的时候,无疑和上面的例子一样,找到B就不找了,直接打印"i am B"。但如果是只有H和E有show方法呢?
class H():
def show(self):
print('H()->show')
class D(H):
pass
class C(D):
pass
class B(C):
pass
class G(H):
pass
class F(G):
pass
class E(F):
def show(self):
print("E()->show")
class A(B,E):
pass
A().show()
我们想当然地以为会打印"i am H",因为深度优先嘛。但是,打印的却是"i am E"!为什么?因为在这种情况下,Python的搜索路径是这样的:
遇到更复杂的继承情况呢?
上述两种继承图还是不太难的,也不能代表所有!实际上其它的继承模式,仔细一解剖,都能划分成上面两种情况
type和isinstance
-
isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()。
-
isinstance() 方法的语法:
-
isinstance(object, classinfo) 参数: object -- 实例对象。 classinfo -- 可以是类名、基本类型或者有它们组成的元组。 返回值: 如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False。
-
#isinstance和type的基本使用
-
-
type:返回对象的类型
-
isinstance() 与 type() 区别:
ce() 与 type() 区别: