活动地址:CSDN21天学习挑战赛
目录
前言
计算机编程中最常被提到的就是类和对象,掌握类和对象,有助于使用Python编程语言快速实现复杂的项目。
一、面向对象是什么?
在现实生活中,人的思考是抽象的,我们会将遇到的事物抽象化,这时就出现了对象的类型——类。先定义类,然后由类去创建对象,最后由对象去管理程序。就像人类思考一样,先抽象,后实例化,最后去执行。面向对象编程就是一种不断抽象数据和不断抽象方法的过程。
二、什么是对象?
万物皆对象。现实世界中我们能见到的、能触碰到的所有人和事物都是对象,如人、猫、狗、汽车等。在计算机世界里,我们用虚拟的编程代码将现实世界里的事物抽象成对象,然后用面向对象编程思想来解决现实世界中的种种难题。人们在认识世界时,会将对象简单处理为两部分——属性和行为。
对象具有属性,它可以称为状态,也可以称为变量。正如每个工厂有名称、位置、面积、产品等属性,我们可以用这些数据来描述对象的属性。
举例:对象“工厂”的属性
对象具有行为,也可以称为方法,就如同每个工厂都要能做:检验、组装、包装、出货。面向对象编程将完成某个功能的代码块定义为方法,方法可以被其他程序调用,也可以被对象自身调用。
举例:对象“工厂”的行为
三、面向对象的重要术语
- 类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。
- 类属性:类属性在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外,通常不作为实例变量使用。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖,也称为方法的重写。
- 实例属性:定义在方法中,只作用于当前实例的类。
- 封装:把需要重用的函数或者功能封装,方便其他程序直接调用
- 继承:指一个派生类继承基类的字段和方法。继承也允许把一个派生类的对象作为一个基类地对象对待。
- 多态(polymorphism):一个函数有多种表现形式,调用一个方法有多种形式,但是表现出的方法是不一样的。
- 实例化:创建一个类的实例,一个类的具体对象。
- 方法:类中定义的函数。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
四、类的语法
类必须被定义后才能使用,定义一个类也就是定义这一类对象的模板,定义它的属性和方法。Python中提供了class关键字来声明一个类,class中有成员属性和成员方法。Python中类的定义格式如下:
class [类名]:
[语法块]
定义一个类的3要素:
- 类名:这类事物的名字,满足大驼峰命名法( 说明:每个单词首字母大写)
- 属性:这类事物具有什么样的特征
- 方法:这类事物具有什么样的行为
定义一个类:
需求:
工厂检验区、工厂组装区、工厂包装区、工厂出货区
分析:
定义一个工厂类
定义4个方法:检验、组装、包装、出货
按照需求,不需要定义属性
class Factory:
'''这是一个工厂类'''
def jianyan(self):
print('这是工厂里面负责检验的。')
def zuzhuang(self):
print('这是工厂里面负责组装的。')
def baozhuang(self):
print('这是工厂里面负责包装的。')
def chuhuo(self):
print('这是工厂里面负责出货的。')
factory1=Factory()
factory1.jianyan()
factory1.zuzhuang()
factory1.baozhuang()
factory1.chuhuo()
#下面是输出
'''
这是工厂里面负责检验的。
这是工厂里面负责组装的。
这是工厂里面负责包装的。
这是工厂里面负责出货的。
'''
五、方法中的self参数
由哪一个对象调用的方法,方法内的 self 就是 哪一个对象的引用
- 在类封装的方法内部,self 就表示 当前调用方法的对象自己
- 调用方法时,不需要传递 self 参数
- 在方法内部,通过 self. 访问 对象的属性
- 在类的外部,通过 实例名. 访问 对象的属性和方法
六、__方法名__格式的方法
这种格式的方法是Python提供的内置方法,说明如下:
方法名 | 类型 | 作用 |
---|---|---|
__new__ | 方法 | 创建对象时,会被 自动 调用。用于控制生成一个新实例的过程,它是类级别的方法。至少要有一个参数cls,代表要实例化的类。__new__方法的调用是发生在__init__之前的。 |
__init__ | 方法 | 对象被初始化时,会被 自动 调用。用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。 |
__del__ | 方法 | 对象被从内存中销毁前,会被 自动 调用。 |
__str__ | 方法 | 返回对象的描述信息,print 函数输出使用。当使用 print 输出对象的时候,只要自己定义了__str__方法,那么就会打印从在这个方法中return的数据。
|
七、初始化方法(__init__)
当使用 类名()创建对象时,会自动执行以下操作:
- 为对象在内存中分配空间——创建对象
- 为对象的属性 设置初始值——初始化方法(__init__)
这个初始化方法,就是__init__方法,__init__方法是对象的内置方法。
__init__方法是专门用来定义一个类具有哪些属性的方法。
示例:
在Factory中增加__init__方法,验证该方法在创建对象时会被自动调用。
class Factory: '''这是一个工厂类''' def __init__(self): print('这是一个初始化方法,创建对象时,会被自动调用!') factory1=Factory() #输出: ''' 这是一个初始化方法,创建对象时,会被自动调用! '''
八、在初始化方法(__init__)内部定义属性
在 __init__
方法内部使用 self.属性名 =属性的初始值 就可以定义属性。
在定义属性之后,再使用Cat类创建对象,都会拥有该属性。
class Factory:
'''这是一个工厂类'''
def __init__(self):
print('这是一个初始化方法,创建对象时,会被自动调用!')
#self.属性名=属性的初始值
self.name='X工厂'
def jianyan(self):
print('这是工厂里面负责检验的。')
#使用类名()创建对象时,会自动调用初始化方法__init__
factory1=Factory()
factory1.jianyan()
print(factory1.name)
#输出:
'''
这是一个初始化方法,创建对象时,会被自动调用!
这是工厂里面负责检验的。
X工厂
'''
九、改造初始化方法(__init__)——初始化的同时设置初始值
在开发过程中,如果希望在 创建对象的同时,就设置对象的属性,就可以对 __init__
方法进行改造。
- 把希望设置的属性值,定义成
__init__
方法的参数 - 在方法内部使用
self.属性 =形参
接收外部传递的参数 - 在创建对象时,使用
类名(属性1,属性2,……)
class Factory:
'''这是一个工厂类'''
def __init__(self,facroty_name):
print('这是一个初始化方法,创建对象时,会被自动调用!')
#self.属性名=属性的初始值
self.name=facroty_name
def jianyan(self):
print('这是工厂里面负责检验的。')
#使用类名()创建对象时,会自动调用初始化方法__init__
factory1=Factory('万向集团')
factory1.jianyan()
print(factory1.name)
#输出:
'''
这是一个初始化方法,创建对象时,会被自动调用!
这是工厂里面负责检验的。
万向集团
'''
十、__del__
方法
当一个对象被从内存中销毁前,再自动调用 __del__
方法
应用场景:
__init__
方法改造初始化方法,可以让创建对象更加灵活
__del__
方法如果希望在对象销毁前,再做一些事情,可以考虑一下这个方法
一个对象从调用 类名()创建,生命周期开始
一个对象的__del__方法一旦被调用,生命周期结束
在对象的生命周期内,可以访问对象属性,或者让对象调用方法
class Factory:
'''这是一个工厂类'''
def __init__(self,facroty_name):
#self.属性名=属性的初始值
self.name=facroty_name
print('{}。'.format(self.name))
def jianyan(self):
print('这是工厂里面负责检验的。')
def __del__(self):
print('{}工厂休假!'.format(self.name))
#使用类名()创建对象时,会自动调用初始化方法__init__
#factory1是一个全局变量
factory1=Factory('万向集团')
factory1.jianyan()
print(factory1.name)
#del关键字可以删除一个对象
del factory1
#输出:
'''
万向集团。
这是工厂里面负责检验的。
万向集团
万向集团工厂休假!
'''
十一、__str__
方法
在Python中,使用 print(对象名),默认情况下会输出:这个变量 引用的对象 是由 哪一个类创建的对象,以及在内存中的地址(十六进制表示)。
class Factory:
'''这是一个工厂类'''
def jianyan(self):
print('这是工厂里面负责检验的。')
factory1=Factory()
print(factory1)
#输出:
'''
<__main__.Factory object at 0x00000235CE8053F0>
'''
如果在开发中使用print输出变量时,能够打印自定义内容,就可以利用 __str__
这个内置方法。
注意:使用 __str__
方法时必须是字符
class Factory:
'''这是一个工厂类'''
def jianyan(self):
print('这是工厂里面负责检验的。')
def __str__(self):
return '我是一个超级工厂!'
factory1=Factory()
print(factory1)
#输出:
'''
我是一个超级工厂!
'''
十二、封装
将属性和方法封装到一个抽象的类中,对象方法的细节都被封装在类的内部。
class Factory:
'''这是一个工厂类'''
def jianyan(self):
print('这是工厂里面负责检验的。')
def zuzhuang(self):
print('这是工厂里面负责组装的。')
def baozhuang(self):
print('这是工厂里面负责包装的。')
def chuhuo(self):
print('这是工厂里面负责出货的。')
factory1=Factory()
factory1.jianyan()
factory1.zuzhuang()
factory1.baozhuang()
factory1.chuhuo()
#下面是输出
'''
这是工厂里面负责检验的。
这是工厂里面负责组装的。
这是工厂里面负责包装的。
这是工厂里面负责出货的。
'''
十三、私有属性
在实际工作中,我们有时候需要限制实例随意修改属性,这时候就要用到私有属性。定义私有属性很简单,只要在定义属性名字的前面使用两条下划线作为开头。
class Factory:
'''这是一个工厂类'''
def __init__(self,name,money):
self.name=name
self.__money=money
print('公司名字叫:{}'.format(self.name))
print('公司有{} 资产。'.format(__money))
def jianyan(self):
print('这是工厂里面负责检验的。')
factory1=Factory('X超级工厂',99999999)
factory1.jianyan()
#输出:
'''
公司名字叫:X超级工厂
Traceback (most recent call last):
File "G:\Python Project Center\面向对象学习.py", line 15, in <module>
factory1=Factory('X超级工厂',99999999)
File "G:\Python Project Center\面向对象学习.py", line 7, in __init__
print('公司有{} 资产。'.format(__money))
NameError: name '_Factory__money' is not defined
'''
十四、私有方法
私有方法和私有属性一样,私有方法只能在类内部被调用,实例不能直接调用。
class Factory:
def __inf(self):
print('超级工厂')
def zuzhuang(self):
print('这里负责组装')
factory1=Factory()
factory1.zuzhuang()
factory1.__inf()
#输出
'''
Traceback (most recent call last):
File "G:\Python Project Center\面向对象学习.py", line 10, in <module>
factory1.__inf()
AttributeError: 'Factory' object has no attribute '__inf'
这里负责组装
'''
十五、继承
继承,是一种对类进行分层划分的概念,继承的基本思想是在一个类的基础上制定出一个新的类,这个新的类不仅可以继承原来类的属性和方法,还可以增加新的属性和方法。原来的类被称为父类,新的类被称为子类。
继承:实现代码的重用 相同的代码不需要重复的编写。
继承的语法:
class 类名(父类名):
pass
子类继承父类,可以直接享受父类封装好的方法,不需要再次开发
class Factory:
def jianyan(self):
print('这是工厂里面负责检验的。')
def zuzhuang(self):
print('这是工厂里面负责组装的。')
def baozhuang(self):
print('这是工厂里面负责包装的。')
def chuhuo(self):
print('这是工厂里面负责出货的。')
class QiCheFactory(Factory):
def jinrong(self):
print('这里提供金融服务!')
x_car=QiCheFactory()
x_car.chuhuo()
x_car.jinrong()
#输出:
'''
这是工厂里面负责出货的。
这里提供金融服务!
'''
继承的时候需要注意:
1、在继承中,如果子类定义了__init__方法,则父类的__init__方法不会被自动调用,需要在子类的__init__方法中专门调用。
class Factory:
def __init__(self,name):
self.name=name
def jianyan(self):
print('这是{},里面负责检验的。'.format(self.name))
class QiCheFactory(Factory):
def __init__(self):
print('超级工厂!')
def jinrong(self):
print('这里提供金融服务!')
x_car=QiCheFactory()
x_car.jianyan()
#输出:
'''
Traceback (most recent call last):
File "G:\Python Project Center\面向对象学习.py", line 16, in <module>
x_car.jianyan()
File "G:\Python Project Center\面向对象学习.py", line 6, in jianyan
print('这是{},里面负责检验的。'.format(self.name))
AttributeError: 'QiCheFactory' object has no attribute 'name'
超级工厂!
'''
我们可以使用super函数调用__init__方法。
class Factory:
def __init__(self,name):
self.name=name
def jianyan(self):
print('这是{},里面负责检验的。'.format(self.name))
class QiCheFactory(Factory):
def __init__(self):
super(QiCheFactory,self).__init__('超级工厂')
def jinrong(self):
print('这里提供金融服务!')
x_car=QiCheFactory()
x_car.jianyan()
#输出:
'''
这是超级工厂,里面负责检验的。
'''
2、子类不能继承父类中的私有方法,也不能调用父类的私有方法。
class Factory:
def __init__(self,name):
self.name=name
def jianyan(self):
print('这是{},里面负责检验的。'.format(self.name))
def __jianyan(self):
print('这是{},里面负责检验重要物料。'.format('特殊车间'))
class QiCheFactory(Factory):
def __init__(self):
pass
def jinrong(self):
print('这里提供金融服务!')
x_car=QiCheFactory()
x_car.jianyan()
x_car.__jianyan()
#输出:
'''
Traceback (most recent call last):
File "G:\Python Project Center\面向对象学习.py", line 21, in <module>
x_car.__jianyan()
AttributeError: 'QiCheFactory' object has no attribute '__jianyan'. Did you mean: 'jianyan'?
这是超级工厂,里面负责检验的。
'''
十六、多态
不同的子类对象调用相同的父类方法,产生不同的执行结果:
- 多态可以增加代码的灵活度
- 以继承和重写父类方法为前提
- 是调用方法的技巧,不会影响到类的内部设计
class Factory:
def shengchan(self):
print('我们负责生产高铁。')
class QiCheFactory(Factory):
def shengchan(self):
print('我们负责生产汽车。')
class LunTaiFactory(Factory):
def shengchan(self):
print('我们负责生产轮胎。')
qiche=QiCheFactory()
qiche.shengchan()
luntai=LunTaiFactory()
luntai.shengchan()
#输出:
'''
我们负责生产汽车。
我们负责生产轮胎。
'''
分析:
当子类和父类存在相同的方法时,子类的方法会覆盖父类的方法,这样代码在运行时总是会调用子类的方法,这就是多态。
多态的意思就是多种形态。多态意味着即使不知道变量所引用的对象时什么类型,也能对对象进行操作。多态会根据类的不同而表现出不同的行为。
判断一个实例是不是某个对象,可以使用isinstance函数。举例如下:
class Factory:
def shengchan(self):
print('我们负责生产高铁。')
class QiCheFactory(Factory):
def shengchan(self):
print('我们负责生产汽车。')
class LunTaiFactory(Factory):
def shengchan(self):
print('我们负责生产轮胎。')
qiche=QiCheFactory()
luntai=LunTaiFactory()
print(isinstance(qiche,QiCheFactory))
print(isinstance(qiche,Factory))
print(isinstance(luntai,LunTaiFactory))
print(isinstance(luntai,Factory))
#输出:
'''
True
True
True
True
'''
十七、类变量
类变量不需要实例化就能直接使用,相当于绑定在类上,而不是绑定在实例上。
class Factory:
name='X工厂'
print(Factory.name)
#输出
'''
X工厂
'''
但是类变量在实例中也是可以被调用的。值得注意的是,实例不能修改类变量。
class Factory:
name='X工厂'
print(Factory.name)
qiche=Factory()
luntai=Factory()
print(qiche.name)
print(luntai.name)
Factory.name='超级工厂'
print(qiche.name)
print(luntai.name)
#输出
'''
X工厂
X工厂
X工厂
超级工厂
超级工厂
'''
十八、静态方法
静态方法和类变量有点类似,静态方法在定义类时就已经被分配定义好了。静态方法并不绑定类也不绑定实例,想当于给方法添加了一个前缀。定义静态方法将引入一个新的概念——装饰器。
定义静态方法的语法就是在定义函数的上面一行(不能有空行)添加一句"@staticmethod"。静态方法不再有第一个默认参数 self。所以静态方法本身也不能调用成员变量和成员方法。静态方法不需要实例化之后使用,和类变量一样直接使用即可,其他的和一般函数没有任何区别。
class Factory:
name='X工厂'
@staticmethod
def inf():
print('本公司是世界五百强!')
Factory.inf()
#输出
'''
本公司是世界五百强!
'''
十九、类方法
类方法,顾名思义就是该方法绑定在定义的类上面,而不是绑定在实例上。
定义类方法和静态方法有点类似,是在定义类方法的前一行(不能有空行)添加一句装饰器"@classmethod"。和静态方法不同的是,类方法和成员方法一样都有一个初始的参数,但是这个参数不同于成员方法。成员方法的第一个参数指向的是实例,而类方法指向的则是定义的类本身,所以类方法可以读取和修改类变量。
class Factory:
name='X工厂'
@classmethod
def inf(cls):
print(cls.name,'世界五百强。')
Factory.inf()
#输出
'''
X工厂 世界五百强。
'''