面向对象编程(Object-Oriented Programming,简称OOP)是一种通过组织对象来设计程序的编程方法。
Python天生就是面向对象的模块化编程。
OOP的四大基本特性是封装、继承、多态和抽象。
1、封装
-
封装是指将对象的属性和方法包装在一起,对外隐藏实现细节,只提供必要的接口给外部访问。
-
在Python中,通过
__init__方法初始化属性,并通过方法来操作这些属性。 -
以
__开头的属性或方法是私有的,在子类和类外部无法直接使用 -
可使用“私有”属性和“公有”方法控制外部访问。
class Dog:
def __init__(self, name, age):
self.__name = name # 私有属性
self.age = age
def get_name(self):
return self.__name
def set_name(self, name):
self.__name = name
dog = Dog('泰迪', 20)
print(dog.get_name())
dog.set_name('哈士奇')
# print(dog._name) # 私有属性不能直接访问,需要通过方法间接访问
print(dog._Dog__name) # 私有属性不能直接访问,需要通过方法间接访问
2 、继承/派生
儿子继承了父亲,父亲派生了儿子~
Python中所有的类最终都继承自内置的object类。
2.1基础概念
继承/派生
继承是从已有的类中派生出新的类,新类具有原类的数据属性和行为,并能扩展新的能力。
派生类就是从一个已有类中衍生出新类,在新的类上可以添加新的属性和行为
继承/派生的作用
用继承派生机制,可以将一些共有功能加在基类中。实现代码的共享。
在不改变基类的代码的基础上改变原有类的功能
继承/派生名词:
基类(base class)/超类(super class)/父类(father class)
派生类(derived class)/子类(child class)
2.2实现
# 继承是面向对象编程的重要概念,它是指一个类可以从另一个类继承其属性和方法,
# 并可以根据需要对其进行扩展。继承可以使得代码更加灵活、更加易于维护。
class Dog:
def f1(self):
print("f1方法")
def f2(self):
print("f2方法")
class Cat(Dog): # Cat继承了Dog
def f3(self):
print("f3方法")
cat = Cat()
cat.f1()
cat.f2()
cat.f3()
#Cat类继承了Dog类,Cat类可以直接访问Dog类的方法,也可以添加自己的方法。
#继承的好处是可以重用代码,提高代码的复用性,减少代码的冗余度。
3、多态
-
多态是指同一个方法在不同对象上具有不同的行为。
-
通过多态,可以使得不同类型的对象以相同的接口表现出不同的行为。
-
多态的实现通常通过继承和方法重写来实现。
class Animal:
def speak(self):
print("Animal is speaking")
class Dog(Animal):
def speak(self):
print("Woof!")
class Cat(Animal):
def speak(self):
print("Meow!")
def animal_speak(animal):
animal.speak()
dog = Dog()
cat = Cat()
animal_speak(dog) # 输出 "Woof!"
animal_speak(cat) # 输出 "Meow!"
4、重写
重写是面向对象编程的重要概念,它是指子类可以重新定义父类的方法,
使得子类对象在调用父类的方法时,会调用子类的方法。
4.1 对象转字符串重写
对象转字符串函数重写方法
str() 函数的重载方法:
def __str__(self)
如果没有 __str__(self) 方法,则返回repr(obj)函数结果代替
str/repr函数重写示例
class MyNumber:
"""此类用于定义一个自定义的类,用于演示str/repr函数重写"""
def __init__(self, value):
"""构造函数,初始化MyNumber对象"""
self.data = value
def __str__(self):
"""转换为普通字符串"""
return "%s" % self.data
n1 = MyNumber("一只猫")
n2 = MyNumber("一只狗")
print("str(n2) ===>", str(n2))
4.2 内建函数重写
-
__abs__abs(obj) 函数调用 -
__len__len(obj) 函数调用 -
__reversed__reversed(obj) 函数调用 -
__round__round(obj) 函数调用
内建函数 重写示例
file : len_overwrite.py
class MyList:
def __init__(self, iterable=()):
self.data = [x for x in iterable]
def __repr_(self):
return "MyList(%s)" % self.data
def __len__(self):
print("__len__(self) 被调用!")
return len(self.data)
def __abs__(self):
print("__len__(self) 被调用!")
return MyList((abs(x) for x in self.data))
myl = MyList([1, -2, 3, -4])
print(myl.data)
print(len(myl))
print(abs(myl).data)
4.3 运算符重载
-
运算符重载是指让自定义的类生成的对象(实例)能够使用运算符进行操作
-
运算符重载的作用
-
让自定义类的实例像内建对象一样进行运算符操作
-
让程序简洁易读
-
对自定义对象将运算符赋予新的运算规则
-
-
运算符重载说明:
-
运算符重载方法的参数已经有固定的含义,不建议改变原有的意义
-
| 方法名 | 运算符和表达式 | 说明 |
|---|---|---|
__add__(self, rhs) | self + rhs | 加法 |
__sub__(self, rhs) | self - rhs | 减法 |
__mul__(self, rhs) | self * rhs | 乘法 |
__truediv__(self, rhs) | self / rhs | 除法 |
__floordiv__(self, rhs) | self // rhs | 地板除 |
__mod__(self, rhs) | self % rhs | 取模(求余) |
__pow__(self, rhs) | self ** rhs | 幂 |
rhs (right hand side) 右手边
-
二元运算符重载方法格式:
def __xxx__(self, other): ....
-
算术运算符重载示例
class MyNumber:
"""此类用于定义一个自定义的类,用于演示运算符重载"""
def __init__(self, value):
"""构造函数,初始化MyNumber对象"""
self.data = value
def __str__(self):
"""转换为表达式字符串"""
return "MyNumber(%d)" % self.data
def __add__(self, rhs):
"""加号运算符重载"""
print("__add__ is called")
return MyNumber(self.data + rhs.data)
def __sub__(self, rhs):
"""减号运算符重载"""
print("__sub__ is called")
return MyNumber(self.data - rhs.data)
n1 = MyNumber(100)
n2 = MyNumber(200)
print(n1 + n2)
n = n1 - n2
print(n.data)
5、super函数
super() 函数是用于调用父类(超类)的一个方法。
5.1基本使用
-
在子类方法中使用 super().add() 调用父类中已被覆盖的方法
-
使用 super(Child, obj).myMethod() 用于子类对象调用父类已被覆盖的方法
class A:
def add(self, x):
y = x+1
print(y)
class B(A):
def add(self, x):
print("子类方法")
super().add(x)
b = B()
b.add(2) # 3
class Parent: # 定义父类
def myMethod(self):
print('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child, c).myMethod() # 用子类对象调用父类已被覆盖的方法
5.2super().__init__()
通过 super().\_\_init\_\_() 调用父类构造函数,以确保父类的构造函数被正确调用和初始化。
class Parent:
def __init__(self):
print("Parent class constructor called")
self.parent_attribute = "I am a parent attribute"
class Child(Parent):
def __init__(self):
super().__init__()
print("Child class constructor called")
self.child_attribute = "I am a child attribute"
# 创建一个 Child 类的实例
child_instance = Child()
print(child_instance.parent_attribute)
# 输出
# Parent class constructor called
# Child class constructor called
为什么使用 super().__init__()?
-
代码重用:避免在子类中重复父类的初始化代码。
-
正确初始化:确保父类的初始化逻辑(如设置属性、分配资源等)被执行。
1444

被折叠的 条评论
为什么被折叠?



