1、面向对象
类是面向对象的实现手段,面向对象编程的基本思想:解决一个问题,先分析这个问题需要那些功能,根据功能进行分类,分类后对该角色进行封装。面向对象保证了功能的统一性,基于面向对象实现的代码更容易维护。
对象(object)
对象是现实世界中可描述的事物,它可以是有形的也可以是无形的,对象是构成一个世界的一个独立单位,它由数据(描述事物的属性)和作用于数据的操作(体现事物的行为)构成的一个独立操作。
类(class)
从具体的事物中把共同的特征抽取出来,形成一般的概念称为“归类”,忽略事物的非本质特性,关注与目标有关的本质特征,找出事务间的共性,抽象出一个概念模型,就是定义一个类。
封装(encapsulation)
封装是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体的实现细节,这就是封装思想。
继承(inheritance)
继承描述的是类与类之间的关系,通过继承,新生类可以在无需赘写原有类的情况下,对原有类的功能进行扩展。
多态(polymorphism)
多态指同一个属性或行为在父类及其各类派生类中具有不同的语义。
2、类和对象的关系
类是对多个对象共同特征的抽象描述,它是对象的模板。
对象用于描述现实中的个体,它是类的实例。
3、类的定义与访问
#旧式类
"""class 类名:
属性名=属性值
def 方法名(self):
方法体"""
#新式类
"""class 类名(object):
属性名=属性值
def 方法名(self):
方法体"""
#类名必须要使用大驼峰命名法,它是由数字,字母,下划线组成,数字不能开头
class Car(object):
wheels = 4
def driver(self):
print("开车的方法")
def stop(self):
print("停车的方法")
4、对象的创建与使用
#旧式类
"""class 类名:
属性名=属性值
def 方法名(self):
方法体"""
#新式类
"""class 类名(object):
属性名=属性值
def 方法名(self):
方法体"""
#类名必须要使用大驼峰命名法,它是由数字,字母,下划线组成,数字不能开头
class Car(object):
wheels = 4
def driver(self):
print("开车的方法")
def stop(self):
print("停车的方法")
#创建对象
my_car=Car()
my_car1=Car()
#获取对象属性值和调用对象的方法
print(my_car.wheels) #4
my_car1.stop() #停车的方法
#给对象添加属性
my_car.name="宝马"
print(my_car.name) #宝马
5、访问限制
类中定义的属性和方法默认为公有属性和公有方法,该类的对象可以任意访问类的公有成员。为了契合封装原则,保证类中的代码不被外部代码轻易访问。Python支持将类中的成员设置为私有成员,在一定的程度上限制对象对类成员的访问。
class PersonInfo(object):
#默认是公有属性
weight=55
#默认是公有方法
def info(self):
print(f"我的体重是{self.weight}")
person = PersonInfo()
print(person.weight) #55
person.info() #我的体重是55
#结论:类里面创建的属性和方法默认是公有属性和公有方法,可以使用对象直接访问公有属性和公有方法
#python通过在类成员名之前添加双下划线__来定义私有属性,对象无法直接访问私有成员
#语法格式:__属性名;__方法名
#私有属性可通过指代对象本身的默认参数“self”访问,类外部可通过公有方法间接获取类的私有属性
class PersonInfo(object):
#默认是公有属性
__weight=55
#默认是公有方法
def __info(self):
print(f"我的体重是{self.__weight}")
def get_weight(self):
print(self.__weight)
self.__info()
person = PersonInfo()
person.get_weight()
#55
#我的体重是55
6、构造方法
每个类都有一个默认的"__init__()"方法,即构造方法
无参构造方法中可以为属性设置初始值,此时使用该方法创建的所有对象都具有相同的初始值
有参构造方法中可以使用参数为属性设置初始值,此时使用该方法创建的所有对象都具有不用的初始值
class Information(object):
'''存储人员信息'''
#定义无参数构造方法,用于给对象添加属性和设置相同的属性值
#self指的是该类创建出来的对象
def __init__(self):
self.color_skin = "黄皮肤"
xiaoli = Information()
print(xiaoli.color_skin) #黄皮肤
#在类里面定义一个有参数的构造方法
class Information(object):
'''存储人员信息'''
#定义有参数构造方法,用于给对象添加属性和设置不同的属性值
#self指的是该类创建出来的对象
def __init__(self,name,age):
self.color_skin = "黄皮肤"
self.name = name
self.age = age
xiaoli = Information("小李",20)
print(xiaoli.name) #小李
print(xiaoli.age) #20
对象属性和类属性的区别:对象属性只能使用对象进行访问,不能使用类进行访问,类属性可以使用类和对象进行访问
7、析构方法
当一个对象引用计数器数值为0时,就会调用__del__(双下划线)方法,这个方法就是类的析构方法。
# __del__:表示当对象销毁的时候会调用该方法,目的:检测对象是否被销毁
#对象的销毁情况:
#1、在程序运行结束后,程序中所使用的数据都要在内存中进行销毁
#2、在程序运行期间,数据没有被变量使用的时候(引用计数为0),该数据对象也会在内存中销毁
import sys
class Destruction(object):
def __del__(self):
print("该对象被销毁掉")
destruction = Destruction()
#统计该对象的引用计数
print(sys.getrefcount(destruction)) #2
# 为什么是2呢?因为在getrefcount中引用了这个变量,他的这个计数就会加一,比预期的结果会大1
del destruction #删除变量
print("over")
8、类方法
什么是实例方法?
方法里面的第一个参数是self就是实例方法,他代表对象本身,只能由对象调用,无法修改类属性。
类方法中使用装饰器@classmethod修饰,类方法的第一个参数为cls,他代表类本身,即可由对象调用,亦可直接由类调用,可以修改类属性。
class Apple(object):
#定义一个类属性
count = 0
#定义实例方法
def add_one(self):
self.count=1
print("执行了实例方法")
#定义类方法
@classmethod
def add_two(cls):
cls.count=2
print("执行了类方法")
apple = Apple()
apple.add_one() #执行了实例方法
print(Apple.count)
#总结:实例方法只能被实例对象进行访问,不能使用类进行访问,并且实例方法中不能修改类属性
apple.add_two() #可以用对象对类方法进行访问
print(Apple.count) # 2
Apple.add_two()
#总结:类方法可以被实例对象和类进行访问,并且类方法中可以修改类属性
9、静态方法
使用修饰器@staticmethod来标识静态方法。
#语法格式
class 类名:
@staticmethod
def 静态方法名():
方法体
静态方法的参数列表无任何参数,无self参数,因此无法访问类的实例属性,无cla参数,因此也无法访问类属性。静态方法跟定义它的类没有直接的关系,只是起到类似于函数的作用。静态方法可以通过对象名调用,也可以通过类名调用,两者无区别。
类方法和静态方法的区别:
类方法有一个cls参数,使用该参数可以在类方法中访问类的成员,静态方法没有任何默认参数,它无法使用默认参数访问类的成员,更适合与类无关的操作、
- 若要修改实例属性的值,直接使用实例方法
- 若要修改类属性的值,直接使用类方法
若是辅助功能,如打印菜单,可考虑使用静态方法,可以在不创建对象的前提下使用。
class Apple(object): #定义一个类属性 count = 0 #定义实例方法 def add_one(self): self.count=1 print("执行了实例方法") #定义类方法 @classmethod def add_two(cls): cls.count=2 print("执行了类方法") #定义一个静态方法 @staticmethod def static_method(): print(Apple.count) Apple.add_two() Apple().add_one() #1、可以使用类进行访问静态方法 Apple.static_method() ''' 0 执行了类方法 执行了实例方法 ''' #2、使用对象进行访问 apple = Apple() apple.static_method() ''' 2 执行了类方法 执行了实例方法 '''
10、单继承
单继承指子类只继承一个父类
# 定义一个父类
class father(object):
name = "关贞雨"
def family(self):
print("这里是父类")
#定义一个子类
class son(father):
def s(self):
print(f"这里是子类,他的父类是{self.name}")
son1 = son()
print(son.name) #关贞雨
son1.s() #这里是子类,他的父类是关贞雨
son1.family() #这里是父类
#总结:子类在继承父类时会自动拥有父类的属性和方法,这里的属性和方法指的是共有属性和公有方法,私有属性和私有方法是不能被子类继承的
11、多继承
一个子类继承多个父类
# 定义一个父类
class father(object):
name = "关贞雨"
def family(self):
print("这里是父类")
#定义一个父类
class father2(object):
name = "关贞雨2"
def father02(self):
print("这里是第二个父类")
class son(father,father2):
def son01(self):
print("这里是子类")
son1 = son()
print(son.name) #关贞雨
son1.father02() #这里是第二个父类
son1.family() #这里是父类
12、方法的重写
子类继承父类的方法和属性后,若父类无法满足子类的需求,可以进行方法的重写
# 定义一个父类
class father(object):
name = "关贞雨"
def family(self):
print("这里是父类")
class son(father):
def family(self):
print("这里子类中重写的父类")
def son01(self):
print("这里是子类")
son1 = son()
print(son.name) #关贞雨
son1.family() #这里子类中重写的父类
13、super()函数
子类重写了父类的方法,如果还想用父类的方法,那么用super函数实现
# 定义一个父类
class father(object):
name = "关贞雨"
def family(self):
print("这里是父类")
class son(father):
def family(self):
print("这里子类中重写的父类")
super().family()
son1 = son()
print(son.name) #关贞雨
son1.family()
#这里子类中重写的父类
#这里是父类
14、多态
在python中,多态指在不考虑对象类型的情况下使用对象,相比于强类型,Python更推崇鸭子类型(关注对象具有的行为)
#多态:对象调用同一个方法会出现不同的表现结果
#使用场景:强调的是对象想要完成一个功能,此时便可以想到多态
#注意点:使用多态的时候必须提供一个统一的调用函数或方法,使用该函数或者方法完成多态的操作】
#比如:在这里提供一个统一进行移动的函数
class Animal(object):
#在父类的方法中不实现具体的功能代码,是用来规定子类方法的命名,在子类方法中实现具体的功能代码
def move(self):
pass
class Rabbit(Animal):
def move(self):
print("兔子通过蹦蹦跳跳进行移动")
class Snail(Animal):
def move(self):
print("蜗牛通过缓慢爬行进行移动")
def move(obj):
#利用多态的操作完成动物移动的功能,统一的函数
obj.move()
rabbit = Rabbit()
move(rabbit) #兔子通过蹦蹦跳跳进行移动
snail = Snail()
move(snail) #兔子通过蹦蹦跳跳进行移动
#多态的优点:
# 1、拓展性极强,想要让某个类型的对象实现对应的功能,把类定义好,实现对象的方法即可
# # 2、在python里面使用多态,不需要关心对象的类型,只要对象有对应的功能方法就可以