1. 类和对象的基本概念
在面向对象程序设计中,类是一种模板或蓝图,用于描述一类对象。类中定义了对象的属性和行为,对象则是类的实例。对象包括属性和方法,类定义了对象的通用属性和方法,并根据特定需求创建实例。
例如,我们可以定义一个矩形类。每个矩形都有宽度和高度属性,以及计算面积和周长的方法。
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
然后,我们就可以创建矩形对象,并使用它的属性和方法。
rect = Rectangle(3, 4)
print(rect.area()) # 输出 12
print(rect.perimeter()) # 输出 14
1.1 类的属性
类的属性是指与类关联的数据,它可以被所有实例共享。例如,我们可以定义一个计数器类,用于记录创建的对象数量。
class Counter:
count = 0
def __init__(self):
Counter.count += 1
每次创建对象时,计数器值都会自增。
c1 = Counter()
c2 = Counter()
print(Counter.count) # 输出 2
1.2 实例和类的方法
类定义的方法可以被类和实例调用,但是实例方法必须以实例为参数,而类方法则必须以类为参数。
class MyClass:
def instance_method(self):
print('This is an instance method of', self)
@classmethod
def class_method(cls):
print('This is a class method of', cls)
MyClass.class_method() # 输出 This is a class method of <class '__main__.MyClass'>
obj = MyClass()
obj.instance_method() # 输出 This is an instance method of <__main__.MyClass object at 0x00000228FA9DAB80>
MyClass.instance_method(obj) # 与上面等价
1.3 魔术方法
魔术方法是在类定义中使用双下划线(__)命名的特殊方法。它们可以重载默认行为,例如实现对象比较、属性访问等功能。
class Vector:
def __init__(self, elements):
self.elements = elements
def __eq__(self, other):
return self.elements == other.elements
def __add__(self, other):
elements = [a + b for a, b in zip(self.elements, other.elements)]
return Vector(elements)
v1 = Vector([1, 2, 3])
v2 = Vector([1, 2, 3])
v3 = Vector([2, 3, 4])
print(v1 == v2) # 输出 True,因为元素相同
print(v1 + v3) # 输出 Vector([3, 5, 7])
2. 继承和多态
继承是面向对象编程中的一种重要机制,它允许新类使用现有类的属性和方法。子类可以继承父类的属性和方法,并可以重写或添加自己的方法。
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
print('Wang Wang!')
class Cat(Animal):
def make_sound(self):
print('Miao Miao!')
dog = Dog('Tom', 2)
cat = Cat('Lucy', 3)
dog.make_sound() # 输出 Wang Wang!
cat.make_sound() # 输出 Miao Miao!
多态是指在不同情境下,不同对象对同一个方法的响应方式不同。例如,在上例中,不管是 Dog 还是 Cat 都可以调用 make_sound 方法,并且得到不同的输出。
3. 封装和属性访问
封装是指将数据和行为作为一个整体,对外部隐藏实现细节。在 Python 中,我们可以使用属性来实现封装。
class Person:
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
def get_age(self):
return self.__age
def set_age(self, age):
if age >= 0 and age <= 120:
self.__age = age
else:
raise ValueError('Invalid age')
p = Person('Tom', 30)
print(p.get_name()) # 输出 Tom
p.set_name('Jerry') # 修改名字
print(p.get_name()) # 输出 Jerry
p.set_age(90) # 修改年龄
print(p.get_age()) # 输出 90
在上面的例子中,我们将属性名定义为双下划线开头,使其成为私有属性,在类的内部可以访问,但在类的外部无法直接访问。
然后,我们定义了 getter 和 setter 方法,用于间接访问私有属性,并对赋值做了限制,确保数据的安全性。
4. 抽象类和接口
抽象类是一种不能被实例化的类,它只能被用作其他类的基类。抽象类中定义了一些方法,子类需要实现这些方法才能被实例化。
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
class Rect(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
r = Rect(3, 4)
print(r.area()) # 输出 12
print(r.perimeter()) # 输出 14
上面的例子中,我们定义了一个抽象类 Shape,它包含了两个抽象方法 area 和 perimeter。然后定义了一个矩形类 Rect,它继承自 Shape 并实现了这两个方法。这样,我们就可以创建 Rect 的实例,并调用其方法。
接口是一种定义类之间通信协议的方式,它规定了类应该具有哪些方法。在 Python 中,接口可以用抽象类和 ABCMeta 实现。
from abc import ABC, abstractmethod
class Payment(ABC):
@abstractmethod
def pay(self, amount):
pass
class CashPayment(Payment):
def pay(self, amount):
print('Cash payment of', amount, '$')
class CreditCardPayment(Payment):
def pay(self, amount):
print('Credit card payment of', amount, '$')
c = CashPayment()
c.pay(100) # 输出 Cash payment of 100 $
p = CreditCardPayment()
p.pay(200) # 输出 Credit card payment of 200 $
上面的例子中,我们定义了一个 Payment 接口,它包含了一个 pay 方法。然后定义了两个类 CashPayment 和 CreditCardPayment,它们都实现了 pay 方法,用于处理现金和信用卡支付。
总结
本文介绍了 Python 面向对象编程的部分知识点,包括类和对象、继承和多态、封装和属性访问、抽象类和接口等。掌握这些知识点可以帮助我们更好地设计和实现面向对象的程序。