你所需要的,不仅仅是一个好用的代理。
面向对象的三大特性:封装、继承、多态。
在类中对数据的赋值,内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法。
1.封装
# 创建类
classF2:
#init构造函数,在实例化时做一些类的初始化的工作
def__init__(self,name,age):
self.name=name
self.age=age
# 根据类F2创建对象
# 自动执行F2类的__init__方法
obj1=F2('xulaingwei', 18)
#将xuliangwei和18分别封装到obj1和self的name、age属性中
# 根据类F2创建对象
# 自动执行F2类的__init__方法
obj2=F2('jack', 58)
#将Jack和58分别封装到obj2和self的name、age属性中
2.调用封装的内容时,有两种调用情况:
# 创建类
classF2:
def__init__(self,name,age):
self.name=name
self.age=age
obj1=F2('xulaingwei', 18)
print(obj1.name,obj1.age) #直接调用obj1对象的name age属性
obj2=F2('jack', 58)
print(obj2.name,obj2.age) #直接调用obj2对象的name age属性
2.通过self间接调用
执行类中的方法时,需要通过self间接调用被封装的内容
# 创建类
classF2():
def__init__(self,name,age):
self.name=name
self.age=age
defdetail(self):
print (self.name)
print (self.age)
obj1=F2('xuliangwei',18)
obj1.detail() # Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 xuliangwei ;self.age 是 18
obj2=F2('jack',58)
obj2.detail() # Python默认会将obj2传给self参数,即:obj2.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 jack ;self.age 是 58
综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。
练习题:在终端输出如下信息
小明,10岁,男,上山去砍柴
小明,10岁,男,开车去东北
小明,10岁,男,最爱大保健
老李,90岁,男,上山去砍柴
老李,90岁,男,开车去东北
老李,90岁,男,最爱大保健
函数式编程方法:
defkanchai(name,age,gender):
print ("%s,%s岁,%s,上山砍柴" %(name,age,gender))
defqudongbei(name,age,gender):
print ("%s,%s岁,%s,开车去东北" %(name,age,gender))
defdabaojian(name,age,gender):
print ("%s,%s岁,%s,最爱大保健" %(name,age,gender))
kanchai('小明', 10, '男')
qudongbei('小明', 10, '男')
dabaojian('小明', 10, '男')
kanchai('老李', 90, '男')
qudongbei('老李', 90, '男')
dabaojian('老李', 90, '男')
面向对象编程方法:
#!/usr/bin/env python
# Author:xuliangwei
classF1:
#init构造函数
#在实例化时做一些类的初始化的工作
def__init__(self,name,age,gender):
self.name=name
self.age=age
self.gender=gender
defkanchai(self):
print("%s,%s岁,%s,上山砍柴" %(self.name, self.age, self.gender))
defqudongbei(self):
print("%s,%s岁,%s,开车去东北" %(self.name,self.age,self.gender))
defdabaojian(self):
print("%s,%s岁,%s,最爱大保健" %(self.name, self.age, self.gender))
obj1=F1('小明', 10, '男')
obj1.kanchai()
obj1.qudongbei()
obj1.dabaojian()
obj2=F1('老李', 90, '男')
obj2.kanchai()
obj2.qudongbei()
obj2.dabaojian()
#上述对比可以看出,如果使用函数式编程,需要在每次执行函数时传入相同的参数,如果参数多的话,又需要粘贴复制了... ;而对于面向对象只需要在创建对象时,将所有需要的参数封装到当前对象中,之后再次使用时,通过self间接去当前对象中取值即可。
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承。
例如:
猫可以:喵喵叫、吃、喝、拉、撒
狗可以:汪汪叫、吃、喝、拉、撒
classmao:
def 喵喵叫(self):
print ("喵喵叫")
def 吃(self):
print ("吃")
def 喝(self):
print ("喝")
def 拉(self):
print ("拉")
def 撒(self):
print ("撒")
classgou:
def 汪汪叫(self):
print ("汪汪叫")
def 吃(self):
print ("吃")
def 喝(self):
print ("喝")
def 拉(self):
print ("拉")
def 撒(self):
print ("撒")
上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。
如果使用”继承“的思想,如下实现:
动物:吃、喝、拉、撒
猫:喵喵叫(猫继承动物的功能)
狗:汪汪叫(狗继承动物的功能)
class Animal:
defeat(self):
print ("%s 吃 " % (self.name))
defdrink(self):
print ("%s 喝 " % (self.name))
defshit(self):
print ("%s 拉 " % (self.name))
defpee(self):
print ("%s 撒 " % (self.name))
class Cat(Animal):
def__init__(self,name):
self.name=name
self.breed= '猫'
defcry(self):
print ('%s 喵喵叫-->%s' %(self.name,self.breed))
class Dog(Animal):
def__init__(self,name):
self.name=name
self.breed= '狗'
defcry(self):
print ('%s 汪汪叫-->%s' %(self.name,self.breed))
# ######### 执行 #########
c1= Cat('小黑猫')
c1.cry()
c1.eat()
c1.drink()
d1= Dog('小瘦狗')
d1.cry()
d1.eat()
d1.drink()
d1.pee()
##对于面向对性爱那个的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法.(避免重复造轮子)
注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。
1.Python的类可以继承多个类,Java和C#中则只能继承一个类
2.Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是: 深度优先和广度优先
python2经典类,按深度优先来继承的。
python2新式类,按广度有限来继承的。
python3经典类,新式类 是按广度优先来继承的。
经典类(深度优先)
当类是经典类时,多继承情况下,会按照深度优先方式查找
#经典类写法
classA1:
pass
classA2(A1):
pass
经典类,实践测试
classD:
defbar(self):
print ('D.bar')
classC(D):
defbar(self):
print ('C.bar')
classB(D):
defbar(self):
print ('B.bar')
classA(B,C):
defbar(self):
print ('A.bar')
a=A()
a.bar()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> D --> C
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
当类是新式类时,多继承情况下,会按照广度优先方式查找
#新式类写法
classN1(object):
pass
classN2(N1):
pass
新式类,实践测试
classD(object):
defbar(self):
print ('D.bar')
classC(D):
defbar(self):
print ('C.bar')
classB(D):
defbar(self):
print ('B.bar')
classA(B,C):
defbar(self):
print ('A.bar')
a=A()
a.bar()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
经典类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
新式类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
下图,其深度优先遍历顺序为 1->2->4->8->5->3->6->7
下图,其广度优先算法的遍历顺序为: 1->2->3->4->5->6->7->8
多态是面向对象的重要特性,简单点说:一个接口,多种实现。
classF1:
pass
classS1(F1):
defshow(self):
print ('S1.show')
classS2(F1):
defshow(self):
print ('S2.show')
def Func(obj):
print (obj.show())
s1_obj=S1()
Func(s1_obj)
s2_obj=S2()
Func(s2_obj)