Python 是一门支持面向对象编程(OOP)的语言,面向对象编程的核心概念包括类、对象、封装、继承和多态。下面通过具体的范例来详细介绍这些概念的使用
一、类和对象
类是对象的设计稿,定义了对象的属性和方法;对象是类的实例。
# 定义一个类
class Dog:
# 类属性
species = "Canis familiaris"
def __init__(self, name, age):
# 实例属性
self.name = name
self.age = age
# 实例方法
def bark(self):
return f"{self.name} says woof!"
# 创建对象
dog1 = Dog("Buddy", 3)
dog2 = Dog("Lucy", 2)
# 访问属性
print(dog1.name) # 输出: Buddy
print(dog2.age) # 输出: 2
# 调用方法
print(dog1.bark()) # 输出: Buddy says woof!
二、封装
封装是将数据(属性)和操作数据的方法(行为)绑定在一起,并隐藏对象的内部实现细节。通过使用访问修饰符(在 Python 中通常通过命名约定)来控制属性的访问。
class BankAccount:
def __init__(self, account_number, balance):
# 私有属性,通过命名约定,以双下划线开头
self.__account_number = account_number
self.__balance = balance
# 公有方法,用于存款
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return f"Deposited {amount}. New balance: {self.__balance}"
else:
return "Invalid deposit amount."
# 公有方法,用于取款
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
return f"Withdrew {amount}. New balance: {self.__balance}"
else:
return "Insufficient funds or invalid withdrawal amount."
# 公有方法,用于获取余额
def get_balance(self):
return self.__balance
account = BankAccount("123456", 1000)
print(account.deposit(500)) # 输出: Deposited 500. New balance: 1500
print(account.withdraw(200)) # 输出: Withdrew 200. New balance: 1300
print(account.get_balance()) # 输出: 1300
在面向对象编程中,访问修饰符用于控制类的属性和方法的访问权限,即决定哪些代码可以访问这些属性和方法。在 Python 里,虽然没有像 Java、C++ 那样明确的 public
、private
、protected
等访问修饰符关键字,但通过命名约定来实现类似的访问控制效果。下面详细介绍 Python 中基于命名约定的访问修饰符概念。
1、公有属性和方法(无特殊前缀)
在 Python 中,没有任何特殊前缀的属性和方法默认是公有的,这意味着它们可以在类的内部、类的实例以及类外部的任何地方被访问。
class Person:
def __init__(self, name):
# 公有属性
self.name = name
# 公有方法
def say_hello(self):
return f"Hello, my name is {self.name}."
# 创建对象
p = Person("Alice")
# 访问公有属性
print(p.name)
# 调用公有方法
print(p.say_hello())
在上述代码中,name
属性和 say_hello
方法都是公有的,我们可以直接在类外部通过对象实例进行访问和调用。
2、私有属性和方法(双下划线前缀)
当属性或方法名以双下划线 __
开头时,Python 会将其视为私有成员。私有成员在类外部不能直接访问,这在一定程度上实现了对类内部数据和实现细节的封装。
class BankAccount:
def __init__(self, balance):
# 私有属性
self.__balance = balance
# 私有方法
def __calculate_interest(self):
return self.__balance * 0.05
# 公有方法,用于间接访问私有属性和方法
def get_balance_with_interest(self):
interest = self.__calculate_interest()
return self.__balance + interest
# 创建对象
account = BankAccount(1000)
# 尝试直接访问私有属性会报错
# print(account.__balance)
# 调用公有方法间接访问私有属性和方法
print(account.get_balance_with_interest())
在这个例子中,__balance
是私有属性,__calculate_interest
是私有方法。如果在类外部直接访问 __balance
会引发 AttributeError
异常,我们只能通过类内部的公有方法(如 get_balance_with_interest
)来间接访问和操作这些私有成员。
3、受保护的属性和方法(单下划线前缀)
以单下划线 _
开头的属性和方法被视为受保护的成员。这只是一种约定,实际上在 Python 中并没有真正限制对这些成员的访问,但按照编程规范,通常表示这些成员不应该在类外部直接访问,主要供类内部或子类使用。
class Vehicle:
def __init__(self, speed):
# 受保护的属性
self._speed = speed
# 受保护的方法
def _increase_speed(self, amount):
self._speed += amount
class Car(Vehicle):
def accelerate(self):
# 子类可以访问受保护的属性和方法
self._increase_speed(10)
return self._speed
# 创建对象
car = Car(50)
# 虽然可以直接访问受保护的属性,但不建议这样做
# print(car._speed)
print(car.accelerate())
在这个示例中,_speed
是受保护的属性,_increase_speed
是受保护的方法。子类 Car
可以访问这些受保护的成员,而在类外部虽然可以直接访问,但按照约定不应该这样做。
Python 通过命名约定实现了类似访问修饰符的功能,帮助开发者控制类的属性和方法的访问权限,提高代码的安全性和可维护性。
三、继承
继承允许一个类继承另一个类的属性和方法,从而实现代码的复用和扩展。被继承的类称为父类(基类),继承的类称为子类(派生类)。
# 父类
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} makes a sound."
# 子类
class Cat(Animal):
def speak(self):
return f"{self.name} meows."
class Cow(Animal):
def speak(self):
return f"{self.name} moos."
cat = Cat("Whiskers")
cow = Cow("Bessie")
print(cat.speak()) # 输出: Whiskers meows.
print(cow.speak()) # 输出: Bessie moos.
四、多态
多态是指不同的对象可以对同一方法做出不同的响应。在 Python 中,多态通常通过继承和方法重写来实现。
class Shape:
def area(self):
pass
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side * self.side
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
import math
return math.pi * self.radius ** 2
# 定义一个函数,接受一个 Shape 对象并调用其 area 方法
def print_area(shape):
print(f"The area of this shape is {shape.area()}.")
square = Square(5)
circle = Circle(3)
print_area(square) # 输出: The area of this shape is 25.
print_area(circle) # 输出: The area of this shape is approximately 28.274333882308138.
通过这些范例,你可以了解 Python 面向对象编程的基本概念和使用方法。在实际开发中,合理运用类、对象、封装、继承和多态可以提高代码的可维护性、复用性和可扩展性。
五、抽象
在 Python 中,可以定义抽象类和抽象方法,不过需要借助 abc
(Abstract Base Classes,抽象基类)模块来实现。下面为你详细介绍相关概念、使用方法和示例代码。
抽象类和抽象方法的概念
- 抽象类:是一种不能被实例化的类,它主要用于定义一组子类必须实现的接口(方法),起到一种规范和约束的作用,为子类提供一个统一的模板。
- 抽象方法:是在抽象类中声明但没有具体实现的方法,子类必须实现这些抽象方法才能被实例化。
abc
模块提供了 ABC
类(Python 3.4 及以后版本)和 abstractmethod
装饰器,用于定义抽象类和抽象方法。
from abc import ABC, abstractmethod
# 定义抽象类,继承自 ABC
class Shape(ABC):
# 定义抽象方法,使用 @abstractmethod 装饰器
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
# 定义子类,继承自抽象类 Shape
class Square(Shape):
def __init__(self, side):
self.side = side
# 实现抽象方法 area
def area(self):
return self.side * self.side
# 实现抽象方法 perimeter
def perimeter(self):
return 4 * self.side
# 定义另一个子类,继承自抽象类 Shape
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
# 实现抽象方法 area
def area(self):
import math
return math.pi * self.radius ** 2
# 实现抽象方法 perimeter
def perimeter(self):
import math
return 2 * math.pi * self.radius
# 尝试实例化抽象类会报错
# shape = Shape()
# 实例化子类
square = Square(5)
print(f"Square area: {square.area()}, perimeter: {square.perimeter()}")
circle = Circle(3)
print(f"Circle area: {circle.area()}, perimeter: {circle.perimeter()}")
代码解释
- 导入模块:从
abc
模块导入ABC
类和abstractmethod
装饰器。 - 定义抽象类:创建
Shape
类并继承自ABC
,使其成为抽象类。 - 定义抽象方法:在
Shape
类中使用@abstractmethod
装饰器定义area
和perimeter
抽象方法,这些方法没有具体的实现代码,只有方法签名。 - 定义子类:创建
Square
和Circle
类,继承自Shape
抽象类,并实现了area
和perimeter
抽象方法。 - 实例化对象:尝试实例化抽象类
Shape
会引发TypeError
异常,而实例化子类Square
和Circle
则是允许的,因为它们已经实现了所有的抽象方法。
通过这种方式,Python 可以实现抽象类和抽象方法的功能,确保子类遵循统一的接口规范。