文章目录
面对对象基础
使用面向对象编程能够大幅度提高程序的复用率,降低后期的维护成本,提高软件的可靠性和可伸缩性。
面向过程与面向对象
面向过程:首先分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候依次调用这些函数即可。以“五子棋”程序为例,面向过程的设计思路就是首先分析问题的步骤:①开始游戏;②黑子先走;③绘制画面;④判断输赢;⑤轮到白子;⑥绘制画面;⑦判断输赢;⑧返回步骤②;⑨输出最后结果。
面向对象:编程思想把构成问题的事务分解成各个对象,这些对象没有先后的顺序,它们共同作用构成了整个系统。以“五子棋”程序为例,整个系统可以划分为 3 类对象:①玩家对象,即黑白双方;②棋盘对象,负责绘制画面;③规则系统,负责判定诸如犯规、输赢等。第一类对象负责接受用户输入,并告知第二类对象棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象来对棋局进行判定。
面向对象基础概念
- 基本概念
(1)对象:一切事务皆对象。
(2)类:类是对象的模板。一个类所包含的方法和数据描述一组对象的共同属性和行为。 - 主要特征
(1) 封装性:将数据和方法封装在类中,用户只能看到公有方法,并不知道实现方法的细节。类相当于一个黑箱。
(2) 继承性:一个类可以定义另一个类。继承分为单继承(一个子类只有一父类)和多重继承(一个类有多个父类)。
(3) 多态性:同一消息为不同的对象接受时可产生完全不同的行为。
类的定义与使用
类的定义
class Animal:
count=0
legs=[]
#类的初始化函数
def __init__(self,name):
self.name=name
#创建类中的函数
def eat(self):
print("I can eat")
- __init__是该类的初始化函数,当创建一个对象后,会自动调用__init__,用于初始化一个对象的数据;
- 任何python类方法的第一个参数都是self,这个参数类似于java中的this。
类的使用
类是抽象的模板,对象是类的实例。python创建一个对象不需要使用new操作符,直接调用类函数。
dog1=Animal('dog')
dog1.eat()
# I can eat
类的属性和方法
类的属性
class Animal:
count=0
legs=[]
#类的初始化函数
def __init__(self,name):
self.name=name
#创建类中的函数
def eat(self):
print("I can eat")
dog1=Animal('dog')
print(Animal.count) #0
print(Animal.legs) #[]
print(dog1.name) #dog
count、legs、name为该类的数据属性,这些数据属性分为类数据属性(count、legs)和实例数据属性(name)。
类的特殊属性:
类属性 | 含义 |
---|---|
__name__ | 类的名字 |
__doc__ | 类的文档字符串 |
__bases__ | 类的所有父类组成的元素 |
__dict__ | 类的属性组成的字典 |
__module__ | 类所属的模块 |
__class__ | 类对象的类型 |
类的方法
在一个类中,可能出现三种方法:实例方法、类方法和静态方法。
(1) 实例方法
实例方法的第一个参数必须是"self"。
class Animal:
count=0
legs=[]
#类的初始化函数
def __init__(self,name):
self.name=name
#创建类中的函数
def eat(self):
print("I can eat")
dog1=Animal('dog')
dog1.eat() #I can eat
(2) 类方法
类方法以cls作为第一个参数,cls表示类本身,定义时使用@classmethod装饰器。通过cls可以访问类的相关属性。
class Animal:
count=0
legs=[]
#类的初始化函数
def __init__(self,name):
self.name=name
@classmethod
def printClassInfo():
print(cls.__name__)
Animal.printClassInfo() #Animal
cat=Animal('cat')
cat.printClassInfo() #Animal
(3) 静态方法
静态方法没有参数限制,既不需要实例参数,也不需要类参数,定义的时候使用@staticmethod装饰器。
class Animal:
count=5
legs=[]
#类的初始化函数
def __init__(self,name):
self.name=name
@staticmethod
def printClassAttr():
print(Animal.count)
Animal.printClassAttr() # 5
cat=Animal('cat')
cat.printClassAttr() # 5
实例方法只能通过实例进行调用;静态方法和类方法,可以通过类名和实例两种方式进行调用。
特殊的类方法:
类属性 | 含义 |
---|---|
__del__ | 析构函数 |
__len__ | 获得长度 |
__call__ | 函数调用 |
__dict__ | 类的属性组成的字典 |
__add__ | 加运算 |
__sub__ | 减运算 |
访问控制
Python中没有像Java中private、protected等访问控制的关键字,但在Python编码中,使用一些约定来进行访问控制。
(1) 名称前的双下划线
如果一个函数、类方法或属性的名字以两个下划线开始(但不是结束),它是私有的。
(2) 名称前的单下划线
在Python中,一般约定以单下划线“_”开头的变量、函数为模块私有的。也就是说“from 模块名 import *”将不会引入以单下划线“_”开头的变量、函数。
(3) 名称前后的双下划线
这种用法表示Python中特殊的方法名。例如,当定义一个类时,经常会重写“__init__”方法。
构造函数和析构函数
(1) __init__ ()构造方法
构造函数是一种特殊的方法,主要用来在创建对象时初始化对象。若实现了__init__()方法,就调用这个方法。
class test():
def __init__(self):
print("__init__")
def __del__(self):
print("__del__")
def common(self):
print("common")
t1=test()
调用结果:
__init__
__del__
说明在创建t1时,__init__()方法被执行了。
(2) __del__()析构方法
当使用del删除对象时,会调用它本身的析构函数,另外当对象在某个作用域中调用完毕,也会调用析构函数,用来释放内存空间。
类的继承
当一个类被其他的类继承时,被继承的类称为基类,又称为父类。继承其他类属性的类称为派生类,又称为子类。
类的简单继承
class Animal:
def eat(self):
print(self.name+' eat')
def drink(self):
print(self.name+' drink')
class Cat(Animal):
def __init__(self,name):
self.name=name
def miaomiao(self):
print('miaomiao')
class Dog(Animal):
def __init__(self,name):
self.name=name
def wangwang(self):
print('wangwang')
c1=Cat('jerry')
c1.eat()
d1=Dog('mike')
d1.drink()
运行结果:
jerry eat
mike drink
当在Python中出现继承的情况时,一定要注意初始化函数__init__的行为。
(1) 如果子类没有定义自己的初始化函数,父类的初始化函数会被默认调用;如果要实例化子类的对象,则只能传入父类的初始化函数对应的参数,否则会出错。
(2) 如果子类定义了自己的初始化函数,而没有显式调用父类的初始化函数,则父类的属性不会被初始化。
(3) 如果子类定义了自己的初始化函数,显式调用父类,则子类和父类的属性都会被初始化。
类的多重继承
使用多重继承需要注意圆括号中父类名字的顺序。如果父类中有相同的方法名,而在类中使用时未指定父类名,则Python解释器将从左至右搜索。
class D:
def bar(self):
print('D.bar')
class C(D):
def bar(self):
print('C.bar')
class B(D):
def bar(self):
print('B.bar')
class A(B,C):
pass
a=A()
a.bar() #B.bar
class D:
def bar(self):
print('D.bar')
class C(D):
def bar(self):
print('C.bar')
class B(D):
def bar(self):
print('B.bar')
class A(C,B):
pass
a=A()
a.bar() # C.bar
类的重载
当继承某一个或几个类时,当前定义的类也继承父类的方法。重载,是指重新定义父类中的方法。
方法重载
方法重载指的是重载父类的方法。
#重载了构造函数和show父类的方法
class People:
def __init__(self,name):
self.name=name
def show(self):
print('father')
def setName(self,name):
print(name)
class P1(People):
def __init__(self,name,age):
self.name=name
self.age=age
def show(self):
print('son')
p1=P1('mike',23)
p1.show()
p1.setName('marry')
运算符重载
在类中,运算符对应类中的一些专有方法。因此运算符的重载实际上是对运算符对应的专有方法的重载。
例如+操作符对应__add__方法:
class List:
__mylist=[]
def __init__(self,*args):
self.__mylist=[]
for arg in args:
self.__mylist.append(arg)
def __add__(self, n):
for i in range(0,len(self.__mylist)):
self.__mylist[i]=self.__mylist[i]+n
return self.__mylist
def show(self):
print(self.__mylist)
list=List(1,2,3,4,5)
list.show() # [1, 2, 3, 4, 5]
list1=list + 5
print(list1) #[6, 7, 8, 9, 10]