面向过程 着重于做什么
面向对象 oop 着重于谁去做
程序员 看作是造物主
类:具有相同属性和方法的对象的集合
对象 (实例):实实在在的例子,某一个类实例化之后的结构体
-
类(Class)
-
对象的蓝图或模板,定义对象的属性(对象的描述信息,静态数据)和方法(行为)。
-
例如:
汽车类
可以有属性颜色
、品牌
,方法启动()
、刹车()
。
-
-
对象(Object)
-
类的实例,具有具体的属性值和方法实现。
-
例如:
一辆红色特斯拉汽车
是汽车类
的一个对象。
-
优势:便于代码管理,方便迭代更新
python :
class User():
school = "sctl"
def __init__(self,name,age,address,passwd):
self.name = name
self.age = age
self.address = address
self.passwd = passwd
print(f"类空间:{User.__dict__}")
print(User.school)
user1 = User("张三",20,'changsha',123456)
user2 = User("lisi",22,"wuhan","lisi123")
print(f"实例空间1:{user1.__dict__}")
print(user1.name,user2.address,user1.school,user2.school)
user1.school = "sanchuang"
print(user1.school,user2.school)
类空间:{'__module__': '__main__', 'school': 'sctl', '__init__': <function User.__init__ at 0x000001B97716A050>, '__dict__': <attribute '__dict__' of 'User' objects>, '__weakref__': <attribute '__weakref__' of 'User' objects>, '__doc__': None}
sctl
实例空间1:{'name': '张三', 'age': 20, 'address': 'changsha', 'passwd': 123456}
张三 wuhan sctl sctl
sanchuang sctl
属性查找:
1、先在当前实例空间查找属性和方法,找到即刻返回
2、如果在实例空间没找到,通过类对象指针,去类空间查找
3、类空间没有,就去父类查找
实例化的两步过程:
1、创建一个实例:
user1 = User.__new__(User)
User没有new方法,是调用父类的,所以要传递参数,指定创建哪个类的实例,也可以写作
user1 = object__new__(User)
2、对实例进行初始化工作
user1.__init__("zhangsan","123456")
user1同样也是用的类空间里的init方法,也可以写作执行的是User.__init__
这时就需要多一个参数,指定哪个实例去使用,写为User.__init__(user1,"zhangsan","123456")
这两步可以简写为user1 = User("zhangsan","123456")
__new__和__init__的区别:
特性 | __new__ | __init__ |
---|---|---|
职责 | 创建实例 | 初始化实例 |
第一个参数 | cls (类) | self (实例) |
返回值 | 必须返回实例对象 | 无返回值 |
执行顺序 | 先执行 | 后执行 |
应用场景 | 单例、不可变类型、动态实例生成 | 常规属性初始化 |
静态方法、实例方法、类方法
class User():
money = 2000
def __init__(self,name,passwd):
self.name = name
self.passwd = passwd
self.money = 5000
def chongzhi(self,amount): #实例方法,普通方法,第一个参数无须传递,代表实例本事
self.money += amount
print(f"充值了{amount},还剩{self.money}")
@classmethod #被这个装饰器装饰的方法,称为类方法,第一个参数无须传递,代表类本身
def chongzhi2(cls,amount):
cls.money += amount
print(f"充值了{amount},还剩{cls.money}")
@staticmethod #被这个装饰的方法,称为静态方法,无需强制参数
def chongzhi3(amount):
User.money += amount
print(f"充值了{amount},还剩{User.money}")
user1 = User("zhangsan","123456")
user1.chongzhi(1000)
user1.chongzhi2(1000)
user1.chongzhi3(1000)
面向对象三大特点:封装、继承、多态
经典类和新式类(经典类的定义在python3中没有了)
特性 | 经典类(Python 2.x 默认) | 新式类(Python 3.x 唯一类型) |
---|---|---|
继承自 | 不显式继承任何类 | 必须直接或间接继承 object |
定义方式 | class MyClass: | class MyClass(object): (Python 2)class MyClass: (Python 3) |
继承属性方法解析顺序(MRO) | 深度优先(Depth-First) | C3 线性化算法(更合理的多继承顺序) |
关于继承,子类会继承父类的方法
class Animal:
def __init__(self):
self.spical = 'dog'
def eat(self):
print("i can eat")
class Cat(Animal):
pass
a=Cat()
print(a.spical)
这里Cat会继承Animal的__init__方法,所以spical='dog'在a生成时同步生成,属性查找时就在当前的实例中查找。
子类重写(Override) 是指子类通过定义与父类同名的方法或属性,覆盖父类的实现,从而实现 自定义行为 或 扩展功能。子类如果如果想在保留父类的属性前提下,再额外添加属性,可用super方法实现
class Person:
def __init__(self, name):
self.name = name
class Student(Person):
def __init__(self, name, student_id):
super().__init__(name)
self.student_id = student_id # 新增属性
stu = Student("小明", "S001")
print(stu.name) # 输出:小明(继承自父类)
print(stu.student_id) # 输出:S001(子类新增)
像工厂函数也是一种类
例:自定义一个可以进行值排序的字典
class Mydict(dict):
def sort(self):
return dict(sorted(self.items(),key=lambda x:x[1],reverse=True))
d1=Mydict()
d1['x'] = 1
d1['y'] = 4
d1['z'] = 2
print(d1)
print(d1.sort)
#判断类型
print(type(d1),type("abc"))
print(isinstance(d1,Mydict))
print(isinstance(d1,dict))
多态 -- 接口不同形态
python原生支持多态,不需要额外的实现
多态性的实现方式
1. 基于继承和方法重写(运行时多态
class Animal:
def speak(self):
raise NotImplementedError("子类必须实现此方法")
class Dog(Animal):
def speak(self): # 重写父类方法
return "汪汪!"
class Cat(Animal):
def speak(self): # 重写父类方法
return "喵喵!"
def animal_sound(animal: Animal):
print(animal.speak())
# 同一函数处理不同对象
animal_sound(Dog()) # 输出:汪汪!
animal_sound(Cat()) # 输出:喵喵!
2. 基于鸭子类型(动态类型)
Python 不强制要求类型继承,只要对象有对应方法即可视为“兼容”:
class Duck:
def quack(self):
print("鸭子叫:嘎嘎!")
class Person:
def quack(self): # 无需继承,只需同名方法
print("人模仿鸭子叫:嘎嘎!")
def make_quack(obj):
obj.quack()
make_quack(Duck()) # 输出:鸭子叫:嘎嘎!
make_quack(Person()) # 输出:人模仿鸭子叫:嘎嘎!
私有成员
魔术方法:
魔术方法(Magic Methods),也称为 特殊方法(Special Methods) 或 双下方法(Dunder Methods),是 Python 中用于定义类行为的一组内置方法。它们以双下划线(__
)开头和结尾,例如 __init__
、__str__
等。魔术方法允许开发者自定义类的行为,使其更符合 Python 的内置协议。
type -- 元类 创建类的类
object -- 继承的顶点,是所有类的基类
抽象基类(定义接口规范,不能实例化,用于强制规范子类的行为)
from abc import ABC, abstractmethod
# 定义一个抽象基类
class Shape(ABC):
@abstractmethod
def area(self):
"""子类必须实现此方法"""
pass
@abstractmethod
def perimeter(self):
pass
# 子类继承抽象基类
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radius
# 尝试实例化
c = Circle(5)
print(c.area()) # 输出 78.5
# 如果子类未实现所有抽象方法,会报错!
class Square(Shape):
def area(self):
return self.side ** 2
s = Square() # TypeError: 未实现 perimeter 方法