目录
一、面向对象与面向过程
python是典型的面向对象(ojective oriented)的编程语言,类似的还有Java等
C语言等是典型的面向过程的(Produced Oriented)的编程语言
区别:
面向过程编程 | 面向对象编程 | |
解决问题的编程思路 | 怎么做? | 谁来做? |
分析主体 | 解决问题的行为步骤 | 执行者与被执行者 |
操作主体 | 函数 | 对象 |
具象化 | 一个什么都懂的人 | 一个有很多资源的项目经理 |
二者均可实现代码重用和模块化编程,但面向过程简单直接,容易理解(直男式解决方案),面向对象更为复杂,模块化程度更高。从开发角度来看,面向对象比面向过程复杂,从维护和扩展功能的角度上来看,面向对象更容易操作 。
经典问题:如何把大象装进冰箱(把冰箱门打开、把大象放进去、把门关上)
面向过程编程:
打开冰箱→把大象放进去→把冰箱门关上
面向对象编程:
1、判断执行者和被执行者,大象、冰箱、还有一个操作者,由此得出三个不同的类,即大象类、冰箱类、操作者类;
2、定义每个类应具有的功能:
操作者类:能够把大象放进冰箱、能够打开和关闭冰箱
冰箱类:能够存放大象,能够开门和关门
大象类:能够进入冰箱
3、将三个类实例化得到三个具体的实例对象,然后各自执行各自的功能完成操作
二、Python类的用法
2.1 类的概述
类(class):类,是对某个群体的统称。比如,狗和秋田犬都是类。用来描述具有相同属性和方法的对象的集合
实例(instance):类中具体的个体,如忠犬八公
对象(object):类和实例的结合(分别叫类对象和实例对象),对象是行动的主题,我们会说“电脑很强大”,也会说“我的电脑卡了”。前者说的是电脑类(类对象),后者说的是我的电脑(实例对象)
2.2 类的创建
class Computer_systerm: #类的创建
screen = True #类的属性创建
def refresh(self): #类的实例方法创建
print('电脑系统正在更新中......')
属性:即在类中被赋值的变量
方法:类中的定义的函数
实例方法:指类中参数带self的函数
2.3 类的调用
类对象支持两种操作,属性引用和实例化,两者结合即可实现类的调用
步骤:①将类实例化;②通过obj.name语句实现属性和方法的调用(类对象创建后,类命名空间中所有的命名都是有效属性名)
class MyClass: #创建类
i = 12345 #定义属性"i"
def f(self): #定义方法"f()"
return 'hello world'
x = MyClass() #实例化类
print("MyClass 类的属性 i 为:", x.i) #调用类的属性
print("MyClass 类的方法 f 输出为:", x.f()) #调用类的方法
>>>
MyClass 类的属性 i 为: 12345
MyClass 类的方法 f 输出为: hello world
2.4 类的属性
1)公开属性(公开变量)
如2.3所述,包含创建及调用两个过程
2)私有属性(私有变量)
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。即实例不能访问私有属性,私有属性智能在类中的属性或方法中被使用。
在类内部的方法中使用时 self.__private_attrs。
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print (self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount) # 报错,实例不能访问私有变量
2.5 类的方法
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例,而不是类。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
>>>>
<__main__.Test instance at 0x100771878> #self的输出结果,指向的是内存地址,代表的是实例
__main__.Test #self.__class__的输出结果,指向的是类
注:self只是一种习惯性写法,并不是关键字,可以用其他字符代替 ,但一般建议使用self
1)普通实例方法
如2.3所述,包含创建及调用两个过程
2)专有方法:__init__()
与普通方法相比,该方法在实例化后会自动调用,不需要额外的调用语句
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) #不需要写成x.__init__().r、x.__init__().i
>>>输出结果:3.0 -4.5
3)类的专有方法汇总
专有方法 | 作用 |
__init__ | 构造函数,在生成对象时调用 |
__del__ | 析构函数,销毁对象,释放占用的内存空间 |
__repr__ | 打印,转换 |
__setitem__ | 按照索引赋值 |
__getitem__ | 按照索引获取值 |
__len__ | 获得长度 |
__cmp__ | 比较运算 |
__call__ | 函数调用 |
__add__ | 加运算 |
__sub__ | 减运算 |
__mul__ | 乘运算 |
__truediv__ | 除运算 |
__mod__ | 求余运算 |
__pow__ | 乘方 |
2.6 类的继承
1)常规继承
子类可以继承父类的属性和方法,语法如下:
class A(B) #B代表父类名,A代表子类名
2)多重继承
A同时继承B,C,D中的属性和方法,如果有重复的则按就近原则进行继承,语法如下:
class A(B,C,D) #A同时继承B、C、D中的方法
3)子类对父类方法的改写
语法与普通方法定义一致,简单来说,就是在子类中对特定方法进行重新定义
如果想通过子类调用父类中已经被覆盖的方法,可以使用super()函数
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self): #在子类中对父类的方法进行重写
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
4)子类方法定制
即是通过在子类下新建属性和方法,让子类用上父项没有的属性和方法。
或是通过2.6(3)中所示方式对父类方法进行改写。