面向对象
-
前言
编程范式:
编程是 程序 员 用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 , 一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式, 对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式。 不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路, 大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式。 两种最重要的编程范式分别是面向过程编程和面向对象编程。
面向过程编程(Procedural Programming):
Procedural programming uses a list of instructions to tell the computer what to do step-by-step.
面向过程编程依赖 - 你猜到了- procedures,一个procedure包含一组要被进行计算的步骤, 面向过程又被称为top-down languages, 就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。
1.什么是面向对象?
OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效
率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容
2.什么是类什么是对象、又有什么关系?
fun3()
s=print('i am fun3')
return s
class 类:
def __init__(self,name)
self.name=name
self.fun3=fun3()
def func1():
pass
def func2():
pass
obj是对象,实例化的过程
obj =类()
obj.函数1() 方法,每调用obj.fun1()一次执行一次
obj.name 类变量
obj.fun3 类变量,实例化的时候执行一次,每次调用obj.fun3都返回实例化时fun3()所retrun 的 s
3.什么时候适用面向对象?
- 根据一个模板创建某个东西
- 如果多个函数需要传入共同的参数时
- 应用场景
class SSH(object):
def __init__(self,host,port,pwd,username)
self.host=host
...
def connection(self):
self.conn = 和服务器创建连接对象()
def close(self):
self.conn.关闭
def upload(self):
self.conn 使用连接上传文件
def cmd(self):
self.conn 使用连接执行命令
obj=SSH(....)
obj.connection()
obj.upload()
obj.close()
4.self就是调用当前方法的对象
- 静态字段的使用场景,每个对象中保存相同的东西时,可以使用静态字段
class FOO(object):
# 静态字段
#公有属性
country = "中国"
def __init__(self,name,count):
#普通字段
#普通属性
self.name=name
self.count=count
def bar(self):
pass
obj1=FOO('河南',1000000)
obj1.bar#self=obj1
obj2=FOO('山东',10000)
obj2.bar#self=obj2
5.封装
- 什么是封装?
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法 - 封装的作用
1.防止数据被随意修改
2.使外部程序不需要关注对象内部的构造,只需要通过此对外提供的接口进行直接访问即可
class F1:
def __init__(self,arg1):
self.a=arg1
print('F1')
class F2:
def __init__(self,arg2):
self.b=arg2
print('F2')
class F3:
def __init__(self,arg3):
self.c=arg3
print('F3')
o1=F1('alex')
o2=F2(o1)
o3=F3(o2)
###输出alex###
o3.c.b.a
6.继承
- 继承的特性:
通过父类--》子类的方式以最小代码量实现 不同角色的共同点和不同点的同时存在
class F1:
def __init__(self):
print('F1')
def a1(self):
print('F1a1')
def a2(self):
print('F1a2')
class F2(F1):
def __init__(self):
print('F2')
3 def a1(self):
4 self.a2 #self=F3
7 print('F2a1')
def a2(self):
print('F2a2')
class F3(F2):
def __init__(self):
print('F3')
5 def a2(self):
6 print('F3a2')
1 obj=f3()
2 obj.a1()
# F3a2
# F2a1
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
继承的过程,就是从一般到特殊的过程。
要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。
在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。
继承概念的实现方式主要有2类:实现继承、接口继承。
Ø 实现继承是指使用基类的属性和方法而无需额外编码的能力;
Ø 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力(子类重构爹类方法);
在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。
抽象类仅定义将由子类创建的一般属性和方法。
OOP开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。
class SchoolMember(object):
"""学校成员基类"""
member=0
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
self.enroll()
def enroll(self):
"""注册"""
print("just enrolled a new school member[%s]"%self.name)
SchoolMember.member+=1
def tell(self):
print("-----info----:%s"%self.name)
for k,v in self.__dict__.items():
print("\t",k,v)
print('-----end----:%s'%self.name)
def __del__(self,):
"""开除了谁"""
print('开除了[%s]'%self.name)
SchoolMember.member-=1
class School(object):#多继承
"""学校类"""
def open_branch(self,addr):
print("openning new school")
class Teacher(SchoolMember,School):
"""讲师类"""
def __init__(self,name,age,sex,salary,course):
# SchoolMember.__init__(self,name,age,sex)#经典类写法
super(Teacher, self).__init__(name,age,sex)#新式类写法
self.salary=salary
self.course=course
def teaching(self):
print('Teacher [%s] is teaching [%s]'%(self.name,self.course))
class Student(SchoolMember):
def __init__(self,name,age,sex,course,tuition):
SchoolMember.__init__(self,name,age,sex)
self.course=course
self.tuition=tuition
self.amount = 0
def pay_tuition(self,amount):
print("student [%s] has just paied [%s]"%(self.name,amount))
self.amount+=amount
t1=Teacher("wusir",28,"FM",3000,"python")
s1=Student("HaiTao",38,"N/A",'PYS15',300000)
s2=Student("LiChuang",12,"M",'PYS15',11000)
print(SchoolMember.member) #3
del s2
print(SchoolMember.member) #2
# print(t1.__dict__)
t1.tell()
t1.open_branch('shanghai') #多继承
- 多继承时,继承顺序的区别
D,BC,A
python2中:
新式类:广度查询 D->B->C->A
经典类:深度查询 D->B->A
python3中:
均为广度查询
7.多态Polymorphism
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定
python不直接支持多态,可以通过折中的方式实现多态
class Animal:
def __init__(self,name):
self.name=name
def talk(self):
raise NotImplementedError('subclss must implement abtract method')
class Dog(Animal):
def talk(self):
return 'woof!woof!'
class Cat(Animal):
def talk(self):
return 'Meow'
d=Dog('d1')
c=Cat('c1')
# Animal.talk(c)
# a=Animal('lichuang')
# a.talk()
8.经典类vs新式类
class Person(object): #new style
class Person: #classical style
# SchoolMember.__init__(self,name,age,sex)#经典类写法
super(Teacher, self).__init__(name,age,sex)#新式类写法
9.静态方法
- 什么是静态方法?
通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法。普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法。
'''
class F1
@staticmethod
def a1():
print('alex')
F1.a1()
'''
10.类方法
类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
class Dog(object):
name = "我是类变量"
def __init__(self,name):
self.name = name
@classmethod
def eat(self):
print("%s is eating" % self.name)
d = Dog("ChenRonghua")
d.eat()
#执行结果
#我是类变量 is eating
11.属性方法
属性方法的作用就是通过@property把一个方法变成一个静态属性
class Dog(object):
def __init__(self,name):
self.name=name
self.__food=None
@property
def eat(self):
print('%s is eating %s'%(self.name,self.__food))
@eat.setter
def eat(self,food):
print('set to food :%s'%food)
self.__food=food
@eat.deleter
def eat(self):
del self.__food
print('删除了')
def __str__(self):
return "obj:%s"%self.name
# d=Dog('chenronghua')
# d.eat #chenronghua is eating None
# d.eat='baozi' #set to food :baozi
# d.eat #chenronghua is eating baozi
# del d.eat #删除属性方法
# print(Dog.__dict__) #打印类里所有的属性,不包括实例属性
# d=Dog("chenronghua")
# print(d.__dict__) #打印所有实例属性,不包括类属性
d=Dog("chenronghua")
print(d)
12.静态方法,类方法,属性方法的对比
- 字段:
普通字段(保存在对象中)
静态字段(保存在类中) - 方法:
普通方法(保存在类中,调用者对象,至少有一个self参数)
class F1:
def a1(self)
print('alex')
obj = F1()
obj.a1()
静态方法(保存在类中,调用者类(无需创建对象)可以有任意个参数):
class F1
@staticmethod
def a1():
print('alex')
F1.a1()
-
静态方法:
只是名义归类管理,实际上静态方法访问不了类或实例的任何内容
class Dog(object):
def __init__(self,name):
self.name=name
@staticmethod #实际和类没什么关系
def eat():
print(' eating baozi ')
d=Dog('chenronghua')
d.eat()
- 类方法:只能访问类变量,不能访问实例变量
- 属性方法:
把一个方法变成一个静态属性
class Dog(object):
def __init__(self,name):
self.name=name
self.__food=None
@property
def eat(self):
print('%s is eating %s'%(self.name,self.__food))
@eat.setter
def eat(self,food):
print('set to food :%s'%food)
self.__food=food
@eat.deleter
def eat(self):
del self.__food
print('删除了')
d=Dog('chenronghua')
d.eat #chenronghua is eating None
d.eat='baozi' #set to food :baozi
d.eat #chenronghua is eating baozi
del d.eat #删除属性方法