面向对象编程(OOP)是一种强大的编程范式,它允许开发者以更自然、更直观的方式来模拟现实世界中的实体和它们之间的关系。在Python中,OOP通过类、实例、封装、继承和多态等概念来实现。
OOP编程
- 一切皆对象:在Python中,几乎所有内容都可以被视为对象,包括内置的数据类型(如整数、字符串)、函数、模块等。这种设计理念使得Python非常灵活和强大。通过将现实世界中的事务(如灯、汽车、导弹、杯子等)使用类和实例来模拟,我们可以更好地组织和表达程序中的数据和逻辑。
"""
Light: 灯
数据 state
操作 is_open change_state
"""
class Light:
def __init__(self):
self.state = False
self.colors = ['红', '黄', '蓝']
self.current = 0
def is_open(self):
return self.state
def change_state(self):
self.state = not self.state
def get_color(self):
return self.colors[self.current]
def set_color(self):
self.current += 1
if self.current == len(self.colors):
self.current = 0
l0 = Light()
print(l0.is_open())
l0.change_state()
print(l0.is_open())
l0.change_state()
print(l0.is_open())
print(l0.get_color())
l0.set_color()
print(l0.get_color())
l0.set_color()
print(l0.get_color())
l0.set_color()
print(l0.get_color())
l0.set_color()
print(l0.get_color())
类与实例
-
类:是对现实世界或问题域中某种类型的对象的抽象表示。它定义了对象的状态(属性)和行为(方法)。在Python中,使用
class
关键字后跟类名来定义类,类名通常使用大驼峰命名法(CamelCase)。类是抽象的,它只描述了对象应该有的内容和行为,但不包含具体的数据。 -
实例:是类的具体实现,即类的具体对象。通过调用类并传入必要的参数(如果有的话),可以创建类的实例。实例是具体的,它包含了类中定义的所有属性和方法,并且每个实例的属性值可以不同。实例的内容依赖于类,但实例是类的具体体现。
self
- 在Python的类定义中,
self
是一个约定俗成的参数名称,用于表示类的实例本身。在类的方法中,第一个参数通常是self
,它允许我们在方法内部访问类的属性和其他方法。当创建类的实例并调用其方法时,Python会自动将实例本身作为self
参数传递给方法。
魔法函数(特殊方法)
- Python中的魔法函数(也称为特殊方法或双下划线方法)以双下划线开始和结束,它们为Python对象提供了丰富的行为。例如,
__init__
用于初始化新创建的对象,__str__
用于返回对象的字符串表示,__len__
用于获取对象的长度等。此外,还有用于比较(如__eq__
、__ne__
等)和算数运算(如__add__
、__sub__
等)的魔法函数。
"""
以双下划线开头和结尾的函数称为魔法函数
初始化函数不需要自己调用
__init__ 用于初始化self
__str__ 返回实例的字符串表示:自定义内容的字符串
__len__ 使用len函数 返回实例对应的长度:自定以返回的·数值
__eq__ 使用== 触发
__ne__ 使用!= 触发
__gt__ 使用 > 触发
__ge__ 使用>= 触发
__lt__ 使用< 触发
__le__ 使用<= 触发
__add__ 使用 + 触发
__sub__ 使用 - 触发
__mul__ 使用 * 触发
__truediv__ 使用 / 触发
__floordiv__ 使用 // 触发
__mod__ 使用 %触发
__divmod__ 使用div(x,y)触发
"""
class MyClass:
def __init__(self, name, age):
print(f"初始化函数执行了")
self.name = name
self.age = age
def __str__(self):
return f"醒醒了:{self.name}"
def __len__(self):
return len(self.name)
def __eq__(self, other):
return self.age == other.age
def __ne__(self, other):
return self.age != other.age
def __gt__(self, other):
return self.age > other.age
def __ge__(self, other):
return self.age >= other.age
def __lt__(self, other):
return self.age < other.age
def __le__(self, other):
return self.age <= other.age
def __add__(self, other):
return self.age + other.age
def __sub__(self, other):
return self.age - other.age
def __mul__(self, other):
return self.age * other.age
def __divmod__(self, other):
return divmod(self.age, other.age)
def __mod__(self, other):
return self.age % other.age
def __truediv__(self, other):
return self.age / other.age
def __floordiv__(self, other):
return self.age // other.age
mc = MyClass("张飞", 18)
print(mc)
print(len(mc))
mc2 = MyClass("孙尚香", 18)
print(mc == mc2, mc != mc2, mc > mc2, mc >= mc2, mc < mc2, mc <= mc2)
print(mc + mc2, mc - mc2, mc * mc2, mc % mc2, divmod(mc, mc2), mc / mc2, mc // mc2)
构造函数与析构函数
-
构造函数:在Python中,
__init__
方法通常被视为构造函数,因为它用于初始化新创建的对象。然而,严格来说,__new__
方法才是真正的构造函数,它负责创建对象并返回该对象。但通常,我们会在__init__
方法中设置对象的初始状态。通过super().__new__(cls)
(注意这里的cls
是类本身,而不是实例)可以调用父类的__new__
方法来创建对象,但这在大多数情况下是不必要的,因为Python会自动处理。 -
析构函数:在Python中,没有直接对应的析构函数名称,但可以使用
__del__
方法来定义对象销毁时执行的清理操作。然而,需要注意的是,由于Python的垃圾回收机制,__del__
方法的调用时机并不总是可预测的。因此,通常不建议在__del__
方法中执行重要的清理操作,而是应该使用其他机制(如上下文管理器)来管理资源。
"""
构造函数:创建并且返回实例(self)
初始化函数 self已经创建完成,可以向self中添加数据
析构函数: 销毁实例 清理实例内存 实例不在使用则回收实例内存之前汇执行对应的析构函数
"""
class MyClass:
def __new__(cls, *args, **kwargs):
# 调用父类的new方法创建一个实例
instance = super().__new__(cls)
print(f"构造函数执行了", id(instance))
# 将创建好的实例返回 返回给初始化函数
return instance
def __init__(self, name):
print(f"初始化函数执行了", id(self))
self.name = name
def __del__(self):
print(f"析构函数执行了")
mc1 = MyClass("阿拉伯")
print(id(mc1), id(None), mc1 is None)
mc1 = None
print("程序执行完毕 将要退出")
# 程序退出执行析构mc1
class MyOpen:
def __init__(self, filename, mode="r", encoding="utf8"):
self.f = open(filename, mode=mode, encoding=encoding)
def read_all(self):
return self.f.read()
def __del__(self):
self.f.close()
mo = MyOpen("./65.魔法函数.py")
print(mo.read_all())
运行结果:
"D:\python\python 312.exe" D:\pythoncode\python基础代码\66.构造函数与析构函数.py
构造函数执行了 2829035399328
初始化函数执行了 2829035399328
2829035399328 140715215741392 False
析构函数执行了
程序执行完毕 将要退出
"""
以双下划线开头和结尾的函数称为魔法函数
初始化函数不需要自己调用
__init__ 用于初始化self
__str__ 返回实例的字符串表示:自定义内容的字符串
__len__ 使用len函数 返回实例对应的长度:自定以返回的·数值
__eq__ 使用== 触发
__ne__ 使用!= 触发
__gt__ 使用 > 触发
__ge__ 使用>= 触发
__lt__ 使用< 触发
__le__ 使用<= 触发
__add__ 使用 + 触发
__sub__ 使用 - 触发
__mul__ 使用 * 触发
__truediv__ 使用 / 触发
__floordiv__ 使用 // 触发
__mod__ 使用 %触发
__divmod__ 使用div(x,y)触发
"""
class MyClass:
def __init__(self, name, age):
print(f"初始化函数执行了")
self.name = name
self.age = age
def __str__(self):
return f"醒醒了:{self.name}"
def __len__(self):
return len(self.name)
def __eq__(self, other):
return self.age == other.age
def __ne__(self, other):
return self.age != other.age
def __gt__(self, other):
return self.age > other.age
def __ge__(self, other):
return self.age >= other.age
def __lt__(self, other):
return self.age < other.age
def __le__(self, other):
return self.age <= other.age
def __add__(self, other):
return self.age + other.age
def __sub__(self, other):
return self.age - other.age
def __mul__(self, other):
return self.age * other.age
def __divmod__(self, other):
return divmod(self.age, other.age)
def __mod__(self, other):
return self.age % other.age
def __truediv__(self, other):
return self.age / other.age
def __floordiv__(self, other):
return self.age // other.age
mc = MyClass("张飞", 18)
print(mc)
print(len(mc))
mc2 = MyClass("孙尚香", 18)
print(mc == mc2, mc != mc2, mc > mc2, mc >= mc2, mc < mc2, mc <= mc2)
print(mc + mc2, mc - mc2, mc * mc2, mc % mc2, divmod(mc, mc2), mc / mc2, mc // mc2)
进程已结束,退出代码为 0
三大特性
-
封装:封装是面向对象编程的核心特性之一。它通过将对象的数据(属性)和操作数据的方法(行为)结合在一起,形成一个独立的单元,从而隐藏了对象的内部实现细节。封装有助于保护对象的数据不被外部直接访问,提高了程序的安全性和可维护性。
-
继承:继承允许我们定义一个类(子类或派生类)来继承另一个类(父类或基类)的属性和方法。子类可以扩展或修改继承的属性和方法,也可以添加新的属性和方法。继承提高了代码的重用性,使得我们可以基于现有的类来构建更复杂、更具体的类。
"""
object是所有类的父类
Python3中可以省略父类object
object 是基类,父类
Person 是object的子类 是SuperPerson的父类
SuperPerson 是Person的子类
子类拥有父类的功能方法,先在子类中找对应的方法 子类如果没有 则去父类中找 父类也没有则去父类的父类 直到object
"""
import math
# class object:
# pass
class Person(object):
""""""
# def __str__(self):
# return "人"
p1 = Person()
print(p1)
# __class__返回实例的类型
print(p1.__class__)
# __base__返回类的父类
print(Person.__base__)
# __bases__返回父类元组 可以有多个父类
print(Person.__bases__)
class SuperPerson(Person):
""""""
def __str__(self):
return "超人"
sp1 = SuperPerson()
print(sp1)
print(sp1.__class__)
print(SuperPerson.__base__)
print(SuperPerson.__bases__)
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"名字:{self.name} 年纪:{self.age}"
def walk(self):
print(f"走路")
p1 = Person("张飞", 20)
print(p1)
p1.walk()
class SuperPerson(Person):
def __init__(self, name, age, skill):
super().__init__(name, age)
self.skill = skill
def __str__(self):
return f"{super().__str__()} 技能:{self.skill}"
def fly(self):
print(f"飞行")
sp1 = SuperPerson("绿巨人", 30, "变绿")
print(sp1)
sp1.walk()
sp1.fly()
# 点 圆 矩形
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"位置 x:{self.x} y:{self.y}"
p0 = Point(10, 10)
print(p0)
class Circle(Point):
def __init__(self, x, y, r):
super().__init__(x, y)
self.r = r
def __str__(self):
return f"{super().__str__()} r:{self.r}"
def get_area(self):
return self.r ** 2 * math.pi
c0 = Circle(10, 10, 5)
print(c0)
print(c0.get_area())
class Rectangle(Point):
def __init__(self, x, y, w, h):
super().__init__(x, y)
self.w = w
self.h = h
def __str__(self):
return f"{super().__str__()} w:{self.w} h:{self.h}"
def get_area(self):
return self.w * self.h
r0 = Rectangle(10, 10, 5, 5)
print(r0)
print(r0.get_area())
-
多态:多态意味着不同的对象可以对同一消息(即方法调用)作出不同的响应。在Python中,多态是通过方法的重写(子类定义与父类同名的方法)来实现的。多态使得我们可以在不知道对象具体类型的情况下调用其方法,从而提高了程序的灵活性和可扩展性。