面向过程是一种以过程为中心的编程思想。
面向对象程序设计主要针对大型软件设计提出的,次编程方式的实现是基于对类和对象的使用。
总结3大特点:封装,继承,多态
class Car():
def __init__(self,pp="宝马",ys="红色",jg="35W"):#类中的构造方法
self.pp=pp #__init__()为构造函数,在创建一个对象时被调用,第一个参数是self
self.ys=ys #实例属性
self.jg=jg
def jia_shi(self): #公有方法
print("我正驾驶一辆%s色的%s车"%(self.ys,self.pp))
def setter_name(self,n): #调用该方法可以重置该值
self.pp = n
def getter(self): #调用该方法可以获取该值
return self.pp
def __str__(self): #该方法是魔法方法,可以返回这个对象包含的信息
return '你的%s爱车要定期保养'%self.pp
def __del__(self):
print('我已被删除') #该方法为析构方法,每次创建对象后Python解释器默认调用该方法,无需手动调用
car1=Car("奔弛","黑色","40W") #实例化对象
car1.jia_shi() #实例对象调用实例方法
#我正驾驶一辆黑色色的奔弛车
print(car1.pp) #实例对象调用实例属性
#奔弛
print(car1) #调用__str__方法返回字符串
#你的奔弛爱车要定期保养
def car1 #删除对象后无法再调用该对象
总结:实例方法,属性只能被被实例对象调用,类无法调用!这些方法也叫做公有方法。
私有方法
def jia_shi(self): #公有方法
self.__woshijingtai()#私有方法只能在类中通过self调用,对象无法调用
def __woshijingtai(self): #私有方法以双下划线开始
__n = 100 #私有属性
print('我是静态')
car1.jia_shi() #可以间接通过公有方法调用
#我是静态
总结:私有方法和私有属性只能在类中被调用!
类中的属性与方法
class Car():
a = '我是类的属性'
def jia_shi(self): #公有方法
print(self.a)
@classmethod #类方法,用该装饰器进行装饰
def setleifangfa(cls,i): #一般以cls作为第一个参数
cls.a = i
@classmethod
def getleifangfa(cls):
return cls.a
car1.setleifangfa('我要改变私有')
#我要改变私有
print(car1.getleifangfa())
#我要改变私有
总结:实例对象可以调用类的方法与属性,同样可以被类在自身中调用
静态方法
静态方法中不需要额外添加定义参数,因此在静态方法中必须通过类对象来引用
静态方法是一种普通函数,位于定义的命名空间中,它不会对任何实例类进行操作。
class Car():
a = '我是静态方法'
@staticmethod
def get():
print(Car.a)
car1=Car()
car1.get()
#我是静态方法
总结:静态方法用 @staticmethod装饰器装饰,它可以被类,实例对象调用!
继承
父类可以是一个或者多个,不用继承则空着
继承分为多继承与单继承 注意:父类的属性,方法可以继承给子类,父类的私有属性,方法无法被继承!
class Super_A(object):
def __init__(self):
self.name = 'jack'
def info_a(self):
print('我是父类')
class Super_B(Super_A):
def __init__(self):
Super_A.__init__(self) #调用父类的init函数
super().__init__() #也可以用super方法继承过来
self.age = 18
def info_b(self):
print(self.name,self.age)
car2 = Super_B()
car2.info_a()
car2.info_b()
#我是父类
#jack 18
总结:派生类定义 init()时,不会自动调用基类的_init_()函数,想要得到基类的_init()中的信息,由派生类调用基类的_init()函数来对它进行恰当的初始化。
多继承
class Person():
def run(self): # 公开方法在子类中可以直接访问,也可以被覆盖
print('Person 会跑')
def eat(self):
print('Person 会吃')
class Man(Person):
def fight(self):
print('Man 打架')
class Woman(Person):
def taobao(self):
print('Woman 淘宝')
class NvHanzi(Woman, Man): # Hanzi继承了Man、Woman的函数和属性
pass # 空,什么都不做
hanzi = NvHanzi()
hanzi.run()
hanzi.eat()
hanzi.taobao()
hanzi.fight()
运行结果:
Person 会跑
Person 会吃
Woman 淘宝
Man 打架
修改父类的方法,也叫重写
class Person():
def run(self): # 公开方法在子类中可以直接访问,也可以被覆盖
print('Person 会跑')
def eat(self):
print('Person 会吃')
class Man(Person):
def run(self): # 在子类中修改父类的方法,会覆盖Person类(父类)的run函数
print('Man在跑')
m = Man() # 自动调用父类的构造函数
m.run() # Man类中覆盖父类中的run函数,m调用的是Man类中的run函数
运行结果:
Man在跑
多态
多态是面向对象语言的一个基本特性,多态意味着变量并不知道引用的对象是谁,根据引用对象的不同表现不同的行为方式。
class ChuiFengJi: # 我们叫具有吹风功能的事物,叫吹风机
def chui(self): # 吹风功能
print("吹风机 能吹风")
class MeiDi(ChuiFengJi):
def chui(self):
print("美的 能吹风")
class FeiLiPu(ChuiFengJi):
pass
def who_zai_chui(arg):
arg.chui()
c = ChuiFengJi()
m = MeiDi()
f = FeiLiPu()
who_zai_chui(c)
who_zai_chui(m)
who_zai_chui(f)
运行结果:
吹风机 能吹风
美的 能吹风
吹风机 能吹风
由于Python是动态语言,所以,传递给函数 who_zai_chui(a)的参数 a 不一定是 ChuiFengJi 或 ChuiFengJi 的子类型。
任何数据类型的实例都可以,只要它有一个chui()的方法即可,这就是多态。
鸭子类型
鸭子类型:
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
在鸭子类型中,不关注对象的类型,只关注它是如何使用的。
比如:吹风机吹风这个功能,在鸭子类型中,只关注它能不能打吹风,而不关心它是谁。
class ChuiFengJi: # 我们叫具有吹风功能的事物,叫吹风机
def chui(self): # 吹风功能
print("吹风机 能吹风")
class MeiDi(ChuiFengJi):
def chui(self):
print("美的 能吹风")
class FeiLiPu(ChuiFengJi):
pass
class PiXie: # PiXie具有吹风的功能,我们就称PiXie是吹风机,这就是鸭子类型
def chui(self):
print("皮鞋 能吹风")
class WenQuXing: # 不具有吹风的功能,就不是吹风机
pass
def who_zai_chui(arg): # 测试函数,test只接受参数,但是不关心参数arg的类型
arg.chui() # 只关心arg能不能调用call函数,不关心它的类型
c = ChuiFengJi()
m = MeiDi()
f = FeiLiPu()
p = PiXie()
w = WenQuXing()
who_zai_chui(c)
who_zai_chui(m)
who_zai_chui(f)
who_zai_chui(p)