一、OOP

oop就是代码的重用,通过分解代码,最小化代码的冗余以及对现存的代码进行定制来编写程序;OOP模型中有两种对象,类对象和实例对象。类对象提供默认行为,是生产实例对象的工厂;类对象和实例对象都有各自命名空间。

二、python类的主要特性

• class语句创建类对象并将其赋值给变量名
• class语句内的顶层赋值语句会创建类的属性
• 类属性提供对象的状态和行为

三、python实例对象的主要特性

• 每次类调用时,都会创建并返回新的实例对象
• 每个实例对象继承类的属性并获得了自己的命名空间
• 每个实例对象通过构造方法获得每个实例自己的属性

四、创建类和实例对象-类的封装

封装,是将对象的数据与操作数据的方法相结合,通过方法将对象的数据与实现细节保护起来,就称为封装。外界只能通过对象的方法访问对象,因此封装同时也实现了对象的数据隐藏

class Person():
#类的属性--静态属性
country="China"

#封装--初始化方法
def __init__(self,*args):
	self.name=args[0]
	self.age=args[1]
	self.aggr=args[2]
	self.sex=args[3]

#方法
def walk(self,n):
	print("%szoule%sbu"%(self.name,n))


#调用类创建实例对象,自动执行构造方法__init__
jonny=Person('jonny',11,23,'man')

#实例对象调用类的方法
jonny.walk(10)

#实例对象调用类的属性
print(jonny.country)

五、类的继承

单继承

类可以通过继承进行定制;类的继承丰富了软件的层级,在层级较低的地方覆盖现有的属性,让其行为特定化。 在python中,实例对象从类中继承,而类继承于超类 • 超类写在类开头的括号中 • 类从其超类中继承属性 • 实例会继承所有可读取类的属性 • 每次实例对象的属性调用都会进行类树搜索 • 逻辑的修改是通过创建子类,而不是修改超类

#创建父类---经典类
class a():
	a1="11"
#创建子类,继承父类a
class b(a):
	b1="22"
#调用父类的属性
print(b.a1)

以上的例子中父类是经典类,因为父类未继承object类;继承object类的父类是新式类 在python3之后,所有类默认继承object类,就是说所有类都是新式类。

#创建父类---新式类
class a(object):
	a1="11"
#创建子类,继承父类a
class b(a):
	b1="22"
#调用父类的属性
print(b.a1)

在继承中,父类是经典类那么子类就是经典类;父类是新式类,子类就是新式类,Python3之后,所有类都是新式类

多继承

python支持继承多个类,那么在继承父类的属性和方法时改怎么找呢?

class D(object):

	def display(self):
		print('D.display')


class C(D):

	def display(self):
		print('C.display')


class B(D):

	def display(self):
		print('B.display')


class A(B,C):

	def display(self):
		print('A.display')

a=A()
a.display()

多继承中,子类的对象调用一个方法,默认是就近原则,在python2.7之前的经典类中是深度优先,在python3之后的新式类中是广度优先。 执行display方法时,查找顺序为 A--B--C--D

Python3中继承特性的新方法

mro()

类的函数mro()记录了继承的顺序,mro()

A.mro()
结果如下:
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>]

super()

super方法是python3之后版本才有的,用于新式类,super方法是根据调用者的节点位置的广度优先顺序来调用父类的函数或方法的。 两种调用方式 1、父类名.方法名,需要自己传self参数 2、super().方法名,不需要自己传self

class Person(object):
	def __init__(self,name,age,sex):
		self.name=name
		self.age=age
		self.sex=sex

	def eat(self):
		print("eatfood")


class Teacher(Person):
	def __init__(self,name,age,sex,school,cls):
		Person.__init__(self,name,age,sex)
		
	#派生方法
	def score(self):
		print("teacherscore")
	def eat(self):
		print("teachereating")

t1=Teacher("adc",42,"man","127","python1ban")
print(t1.name)

#传入类和对象,调用父类的方法
super(Teacher,t1).eat()

六、类的多态

类的多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。

class Person():
def display(self):
	pass

class Man(Person):
	def display(self):
		print("man")

class Woman(Person):
	def display(self):
		print("woman")



def func(obj):
	obj.display()

#实例化对象
man1=Man()
woman1=Woman()

#多态
func(man1)
func(woman1)

七、组合

一个对象的属性值是另外一个类的对象

class Birthday():
	def __init__(self,year,month,day):
		self.year=year
		self.month=month
		self.day=day

class Person():
	def __init__(self,name,age,birthday):
		self.name=name
		self.age=age
		self.birthday=birthday


bd=Birthday(2019,11,11)

jonny=Person("jonny",20,bd)

#组合调用
print(jonny.birthday.year)

八、派生

父类中没有的属性,在子类中出现,叫做派生属性 父类中没有的方法,在子类中出现,叫做派生方法

class Person(object):
	def __init__(self,name,age,sex):
		self.name=name
		self.age=age
		self.sex=sex

	def eat(self):
		print("eatfood")


class Teacher(Person):
	def __init__(self,name,age,sex,school,cls):
		Person.__init__(self,name,age,sex)
		
	#派生方法
	def score(self):
		print("teacherscore")
	def eat(self):
		print("teachereating")

t1=Teacher("adc",42,"man","127","python1ban")
print(t1.name)

#传入类和对象,调用父类的方法
super(Teacher,t1).eat()

九、面向对象的编程规范:接口类与抽象类

接口类与抽象类的不同点: 接口类:支持多继承,接口类中的所有的方法都必须不能实现;python中没有接口类,java没有多继承,所以为了接口隔离原则,设计了接口这个概念

抽象类:不支持多继承,抽象类中的方法可以有一些代码的实现;python自带多继承,所以直接用class来实现接口类;python支持抽象类,一般情况下单继承,java本来就有单继承,所以就有了抽象类。 接口类与抽象类的相同点: 1、都依赖abc模块实现 2、都是面向对象的编程规范 3、接口类和抽象类都不能实例化

一般情况下,单继承,能实现的功能是一样的,所以在父类中可以有简单的基础实现 多继承的情况下,由于功能比较复杂,所以不容易抽象出相同的功能的具体实现写在父类中

接口类的实现:

from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):#元类,默认的元类type
	@abstractmethod
	def pay(self,money):pass
#raiseNotImplemented#手动抛异常,没有实现这个方法
#规范:接口类或者抽象类都可以
#接口类:支持多继承,接口类中的所有的方法都必须不能实现-----java
#抽象类:不支持多继承,抽象类中的方法可以有一些代码的实现-----java

class Wechatpay():
	defpay(self,money):
	print("微信支付了%s元"%money)

class Alipay():
	defpay(self,money):
	print("ali支付了%s元"%money)

def pay(pay_obj,money):#统一支付接口
	pay_obj.pay(money)

wechat=Wechatpay()
ali=Alipay()

pay(ali,200)

接口类多继承示例:

from abc import ABCMeta,abstractmethod

class Swim_Animal(metaclass=ABCMeta):
	@abstractmethod
	def swim(self):
		pass

class Walk_Animal(metaclass=ABCMeta):
	@abstractmethod
	def walk(self):pass

class Fly_Animal(metaclass=ABCMeta):
	@abstractmethod
	def fly(self):pass
	
class Tiger(Walk_Animal,Swim_Animal):
	def swim(self):pass
	def walk(self):pass

class Swan(Walk_Animal,Swim_Animal,Fly_Animal):
	def swim(self):pass
	def walk(self):pass
	def fly(self):pass


class Oldying(Walk_Animal,Fly_Animal):
	def walk(self):pass
	def fly(self):pass

抽象类示例:

from abc import abstractmethod,ABCMeta

class All_file(metaclass=ABCMeta):
	@abstractmethod
	def read(self):#规范子类必须有的方法
		print("du")
	
	@abstractmethod
	def write(self):
		print("xie")


class Doc(All_file):
	def read(self):pass
	def write(self):pass

classTxt(All_file):
	def read(self):pass
	def write(self):pass
	
class Ppt(All_file):
	def read(self):print("pptdu")
	def write(self):pass

p1=Ppt()
p1.read()