一、面对对象程序设计基础
1. 面对对象程序设计思想概述
面向对象程序设计(Object-Oriented Programming,简称OOP)是一种编程范式,它将数据和操作数据的方法封装在一个对象中。这种方法强调的是将现实世界中的实体抽象为对象,每个对象都有其独特的属性和行为。
在Python中,面向对象编程的实现主要通过以下几个关键概念:
-
类 : 类是创建对象的蓝图,可以看作是一组具有相同属性和行为的对象的集合。
-
对象 : 对象是类的实例,是类在内存中的具体体现。每个对象都有自己的属性(变量)和行为(方法)。
-
属性 : 属性是对象的状态,即对象所拥有的数据。比如说,我们定义学生是一个类,那么我们可以设置类里面的属性有:姓名、班别、学号等。
-
方法 : 也称为成员函数,通常由类定义,用于改变对象的状态或返回对象的状态。比如说,我们定义学生是一个类,那么我们可以设置类里面的方法有:学习、吃饭、睡觉等。
-
继承 : 继承允许创建新类(子类)来扩展或修改现有类(父类)的行为。子类可以继承父类的属性和方法,并添加新的属性和方法。比如说,我们定义学生是一个类,则可以定义“本科生”、“研究生”分别为“学生”这个类的子类。“本科生”子类可以继承“学生”父类的属性(例如姓名、班别、学号等)和方法(例如学习、吃饭、睡觉等),在子类就无需再重复定义。
-
封装 : 将数据和操作捆绑在一起,定义一个新类的过程就是封装。
-
多态 : 多态允许不同的对象对同一消息作出响应。这意味着子类可以覆盖父类的方法,并且当这些方法被调用时,会根据对象的实际类型来执行相应的方法。
-
构造函数 :一种类内的成员函数,用来在创建对象时初始化对象。
-
析构函数 :与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往被用来做“清理善后”工作。
二、 定义和使用类
1. 声明类
使用class 关键字来声明一个类,基本语法:
class 类名:
成员变量
成员函数
class Person: #定义一个Person类
def SayHello(self): #成员函数
print("Hello!")
1.1 self
类的成员函数必须有一个参数 self ,而且位于参数列表的开头。self 就代表类的实例(对象)自身,可以使用 self 引用类的属性和成员函数。
1.2 定义类的对象
对象是类的实例,只有定义了具体的对象,才能使用类。
python创建对象的方法:对象名 = 类名()
class Person:
def SayHello(self):
print("Hello!")
p = Person #创建具体的对象
p.SayHello #调用函数
1.3 成员变量
在类定义中,可以定义成员变量并同时对其赋初始值。
注意:python使用下划线作为变量前缀和后缀来指定特殊变量,
__XXX__:系统定义名字;
__XXX:类中的私有变量名。
class MyString: #定义一个类
str = "MyString" #定义成员变量并赋初始值
def output(self):
print(self.str) #在类的成员函数中使用self
1.4 构造函数
构造函数是类的一个特殊函数,它的名称是固定的:__init__(前后各两个下划线)。当创建类的对象实例时系统会自动调用构造函数,通过构造函数对类进行初始化操作。
class MyString:
def __init__(self): #构造函数
self.str = "MyString" #对公有变量str设置了初始值
def output(self):
print(self.str)
s = MyString() #创建类的对象
s.output()
class UserInfo:
def __init__(self,name,pwd): #构造函数初始化变量
self.username = name #公有变量
self.__pwd = pwd #私有变量
def output(self):
print("用户:"+self.username+"\n密码:"+self.__pwd)
u = UseerInfo("admin","123456") #创建新对象
u.output()
1.5 析构函数
在python中,析构函数有一个固定的名称:__del__。通常在析构函数中释放类所占用的资源。
使用del语句可以删除一个对象,释放他所占用的资源,在实例化对象被回收时将调用析构函数。
class MyString:
def __init__(self): #构造函数
self.str = "MyString"
def __del__(self): #析构函数
print("byebye")
def output(self):
print(self.str)
s = MyString() #创建新对象
s.output()
del s #删除对象
2. 静态变量
静态变量和静态函数是类的静态成员,它们与普通的成员变量和成员函数不同,静态变量和静态函数与具体的对象没有关系,而是只属于定义它们的类。
python不需要显式定义静态变量,任何公有变量都可以作为静态变量使用。访问静态变量的方法:类名.变量名。
class Users:
online_cout = 0
def __init__(self): #构造函数
Users.online_count += 1 #每创建一次对象+1
def __del__(self): #析构函数
Users.online_count -= 1 #每释放一次对象-1
a = Users() #创建对象
a.online_count += 1
print(Users.online_count)
3. 静态方法的使用
与静态变量相同,静态方法只属于定义它的类,而不属于任何一个具体的对象。
特点:
(1)无需传入self参数,因此静态方法中无法访问实例变量;
(2)不可以直接访问类的静态变量,但是可以通过类名引用静态变量;
(3)与定义它的类没有直接关系,而是起到了类似函数工具库的作用。
使用装饰符@staricmethod定义静态方法:
class 类名:
@staticmethod
def 静态方法名():
方法体
class MyClass:
var1 = 'String 1'
@staticmethod #静态方法
def staticma():
print("我是静态方法")
MyClass.staticmd() #使用类调用静态方法
c = MyClass()
c.staticmd() #使用对象调用静态方法
4. 类方法的使用
类方法是python的一个新概念,类方法具有特性:
(1)与静态方法一样,可以使用类名调用类方法;
(2)与静态方法一样,类成员方法也无法访问实例变量,但是可以访问类的静态变量;
(3)类方法需要传入代表本类的cls参数。
使用装饰符@classmethod定义类方法:
class 类名:
@classmethod
def 类方法名(cls):
方法体
class MyClass:
val1 = 'String 1'
def __init__(self): #构造函数
self.val2 = 'Value 2'
@classmethod #类方法
def classmd(cls):
print(cls.val1) #通过参数cls访问类的静态变量
MyClass.classmd()
c = MyClass()
c.classmd()
5. 使用isinstance()函数判断对象类型
使用isinstance()函数可以用来检测一个给定的对象是否属于(继承于)某个类或类型,如果是则返回True,否则返回False。
使用方法:isinstance(对象名,类名或类型名)
class MyClass:
val1 = 'String 1'
def __init__(self): #构造函数
self.val2 = 'Value 2'
c = MyClass() #新建对象
print(isinstance(c,MyClass))
l = [1,2,3,4]
print(isinstance(l,list))
三、 类的继承与多态
1. 继承
如果我们要设计六个类,分别是“一年级学生”、“二年级学生”、“三年级学生”、“四年级学生”、“五年级学生”、“六年级学生”,但是这六个类的代码有很多共同之处,我们可以尝试设计一个“学生”的父类,然后再从其中派生出六个子类,子类拥有父类所有属性和函数。
class A:
def __init__(self,property): #构造函数
self.propertyA = property #A类的成员变量
def function(): #Student类的成员函数
#从A类中派生出B类
class B(A):
propertyB #成员变量
def functionB(): #成员函数
从类B中可以访问到类A中的成员变量和成员函数,例如:
objB = B() #定义一个类B的对象objB
print(objB.propertyA) #访问类A的成员变量
objB.functionA() #访问类A的成员函数
2. 抽象类和多态
抽象类是包含抽象方法的类,而抽象方法不包含任何实现的代码,只能在其子类中实现抽象函数的代码。
2.1 定义抽象类
python需要通过类库abc实现抽象类,因此仔定义抽象类之前需要从类库abc导入ABCMeta类和abstractmethod类。
方法:from abc import ABCMeta,abstractmethod
ABCMeta是抽象基类的元类,在定义抽象类时只需要在类定义中增加如下代码:
__metaclass__=ABCMeta
即指定该类的元类是ABCMeta
在抽象类里面可以定义抽象方法。定义抽象方法时需要在前面加上代码:
@abstractmethod
因为抽象方法不包含任何实现的代码,所以函数体通常使用pass。
class myabc(object):
__metaclass__=ABCMeta
@abstractmethod
def abcmethod(self):
pass
2.2 多态
所谓多态,指抽象类中定义的一个方法,可以在其子类中重新实现,不同子类的实现方法也不同。
例如:创建一个抽象类shape,定义一个画图类的基本框架;
class Shape(object):
__metaclass__=ABCMeta
def __init__(self):
self,color = 'black' #默认使用黑色
@abstractmethod
def draw(self): #定义抽象方法
pass
创建类Shape的子类Circle
class circle(Shape):
def __init__(self,x,y,r): #定义圆心坐标和半径
self.x = x
self.y = y
self.r = r
def draw(self):
print("Draw Circle:(%d,%d,%d)"%(self.x,self.y,self.r))
再从类中派生出画直线的类line
class line(Shape):
def __init__(self,x1,y1,x2,y2): #定义起止坐标值
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
def draw(self):
print("Draw Line:(%d,%d,%d,%d)"%(self.x1,self.y1,self.x2,self.y2))
四、 复制对象
可以通过赋值操作复制对象,方法:新对象名 = 原对象名