类
Python 支持面向对象编程(OOP),允许开发者使用类和对象来组织和管理代码。类是创建对象的蓝图,通过类可以封装数据和功能,促进代码的复用性和可维护性。
名称和对象
在 Python 中,一切皆对象。类本身也是对象,具有自己的属性和方法。每个对象都有一个唯一的身份(ID)、类型(type)和一个值(value)。
- 名称:名称是指向对象的引用,类似于变量名。名称绑定到对象,而不是对象绑定到名称。
- 对象:对象是类的实例,拥有类定义的属性和方法。
示例:
class Dog:
pass
my_dog = Dog()
print(type(my_dog)) # 输出: <class '__main__.Dog'>
Python 作用域和命名空间
作用域(Scope)和命名空间(Namespace)是理解变量解析和访问权限的关键概念。
作用域和命名空间示例
- 局部作用域:函数或方法内部定义的命名空间。
- 全局作用域:模块级别的命名空间。
- 内建作用域:Python 解释器启动时创建的命名空间,包含内置函数和异常。
示例:
x = "全局变量"
def foo():
x = "局部变量"
print(x)
foo() # 输出: 局部变量
print(x) # 输出: 全局变量
初探类
类是创建对象的蓝图,定义了对象的属性和行为。通过类,可以创建多个实例,每个实例都有自己的属性值。
类定义语法
使用 class
关键字定义类,类名通常采用大驼峰命名法。
示例:
class Dog:
"""一个简单的狗类"""
def __init__(self, name, age):
"""初始化属性"""
self.name = name
self.age = age
def sit(self):
"""模拟小狗被命令时蹲下"""
print(f"{self.name} is now sitting.")
def roll_over(self):
"""模拟小狗被命令时打滚"""
print(f"{self.name} rolled over!")
Class 对象
类本身也是对象,属于 type
类型。可以动态地为类添加属性和方法。
示例:
class MyClass:
pass
print(type(MyClass)) # 输出: <class 'type'>
# 动态添加属性
MyClass.attr = "类属性"
print(MyClass.attr) # 输出: 类属性
实例对象
实例对象是根据类创建的具体对象,拥有类定义的属性和方法。
示例:
my_dog = Dog('Willie', 6)
print(f"My dog's name is {my_dog.name}.") # 输出: My dog's name is Willie.
print(f"My dog is {my_dog.age} years old.") # 输出: My dog is 6 years old.
my_dog.sit() # 输出: Willie is now sitting.
方法对象
方法是类中的函数,定义了对象的行为。方法的第一个参数通常为 self
,代表实例本身。
示例:
class Cat:
def __init__(self, name):
self.name = name
def meow(self):
print(f"{self.name} says Meow!")
my_cat = Cat('Whiskers')
my_cat.meow() # 输出: Whiskers says Meow!
类和实例变量
- 类变量:属于类本身,所有实例共享。定义在类体中,但不在任何方法内。
- 实例变量:属于每个实例,互不影响。通常在
__init__
方法中通过self
定义。
示例:
class Bird:
species = '鸟类' # 类变量
def __init__(self, name):
self.name = name # 实例变量
bird1 = Bird('Sparrow')
bird2 = Bird('Eagle')
print(bird1.species) # 输出: 鸟类
print(bird2.species) # 输出: 鸟类
bird1.species = '麻雀' # 修改实例变量,不影响类变量
print(bird1.species) # 输出: 麻雀
print(bird2.species) # 输出: 鸟类
print(Bird.species) # 输出: 鸟类
补充说明
特殊方法
类中可以定义特殊方法(如 __init__
, __str__
, __repr__
等)来定制对象的行为。这些方法以双下划线开头和结尾,具有特定的用途。
示例:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"Point({self.x}, {self.y})"
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
p = Point(1, 2)
print(p) # 输出: Point(1, 2)
print(repr(p)) # 输出: Point(x=1, y=2)
描述符
描述符是实现了 __get__
, __set__
, __delete__
方法的类,用于管理属性访问。
示例:
class Descriptor:
def __init__(self):
self.value = None
def __get__(self, obj, objtype):
return self.value
def __set__(self, obj, value):
if not isinstance(value, int):
raise ValueError("必须是整数")
self.value = value
def __delete__(self, obj):
del self.value
class MyClass:
attr = Descriptor()
instance = MyClass()
instance.attr = 10
print(instance.attr) # 输出: 10
# instance.attr = "Hello" # 将引发 ValueError: 必须是整数
属性(Properties)
使用 @property
装饰器将方法转换为属性,实现属性的获取、设置和删除操作,增强封装性。
示例:
class Temperature:
def __init__(self, kelvin):
self._kelvin = kelvin
@property
def kelvin(self):
return self._kelvin
@kelvin.setter
def kelvin(self, value):
if value < 0:
raise ValueError("温度不能低于绝对零度")
self._kelvin = value
@kelvin.deleter
def kelvin(self):
del self._kelvin
temp = Temperature(300)
print(temp.kelvin) # 输出: 300
temp.kelvin = 310
print(temp.kelvin) # 输出: 310
# temp.kelvin = -5 # 将引发 ValueError: 温度不能低于绝对零度
继承
继承是面向对象编程的核心概念之一,允许子类继承父类的属性和方法,实现代码复用和扩展。
多重继承
一个子类可以继承多个父类,形成多重继承关系。Python 使用方法解析顺序(MRO)来确定方法和属性的搜索顺序。
示例:
class Mother:
def skills(self):
print("Cooking")
class Father:
def skills(self):
print("Driving")
class Child(Mother, Father):
def skills(self):
Mother.skills(self)
Father.skills(self)
print("Programming")
child = Child()
child.skills()
# 输出:
# Cooking
# Driving
# Programming
私有变量
通过命名约定控制属性和方法的访问权限,增强封装性和数据保护。
命名约定
- 单前导下划线
_
:表示受保护的属性或方法,建议内部使用,外部不直接访问。 - 双前导下划线
__
:触发名称重整(Name Mangling),使属性在类外部难以访问。
示例:
class MyClass:
def __init__(self):
self.public = "公开属性"
self._protected = "受保护属性"
self.__private = "私有属性"
def public_method(self):
print("公开方法")
def _protected_method(self):
print("受保护方法")
def __private_method(self):
print("私有方法")
obj = MyClass()
print(obj.public) # 输出: 公开属性
print(obj._protected) # 输出: 受保护属性
# print(obj.__private) # 将引发 AttributeError
obj.public_method() # 输出: 公开方法
obj._protected_method() # 输出: 受保护方法
# obj.__private_method() # 将引发 AttributeError
# 通过名称重整访问私有属性(不推荐)
print(obj._MyClass__private) # 输出: 私有属性
obj._MyClass__private_method() # 输出: 私有方法
使用 property
控制访问
通过 @property
装饰器和相应的装饰器控制属性的访问和修改,提供更好的封装。
示例:
class BankAccount:
def __init__(self, balance=0):
self._balance = balance
@property
def balance(self):
return self._balance
@balance.setter
def balance(self, amount):
if amount < 0:
raise ValueError("余额不能为负数")
self._balance = amount
@balance.deleter
def balance(self):
del self._balance
account = BankAccount(100)
print(account.balance) # 输出: 100
account.balance = 150
print(account.balance) # 输出: 150
# account.balance = -50 # 将引发 ValueError: 余额不能为负数
杂项说明
方法装饰器
除了 @property
,还有其他方法装饰器如 @classmethod
和 @staticmethod
,用于定义类方法和静态方法。
示例:
class MyClass:
@classmethod
def class_method(cls):
print("这是一个类方法")
@staticmethod
def static_method():
print("这是一个静态方法")
MyClass.class_method() # 输出: 这是一个类方法
MyClass.static_method() # 输出: 这是一个静态方法
动态添加属性和方法
类和实例在运行时可以动态添加属性和方法,增强灵活性。
示例:
class Dynamic:
pass
obj = Dynamic()
obj.new_attr = "新属性"
print(obj.new_attr) # 输出: 新属性
def new_method(self):
print("这是动态添加的方法")
import types
obj.new_method = types.MethodType(new_method, obj)
obj.new_method() # 输出: 这是动态添加的方法
迭代器
类可以实现迭代器协议,使其实例能够在 for
循环中使用。迭代器需要实现 __iter__
和 __next__
方法。
示例:
class MyIterator:
def __init__(self, limit):
self.limit = limit
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current < self.limit:
num = self.current
self.current += 1
return num
else:
raise StopIteration
iterator = MyIterator(3)
for num in iterator:
print(num)
# 输出:
# 0
# 1
# 2
生成器
生成器是一种简化迭代器创建的方法,通过 yield
关键字生成值。生成器使代码更简洁,节省内存。
示例:
def my_generator(limit):
current = 0
while current < limit:
yield current
current += 1
for num in my_generator(3):
print(num)
# 输出:
# 0
# 1
# 2
生成器表达式
生成器表达式是一种简洁的生成器的语法,类似于列表推导式,但使用圆括号 ()
。
示例:
gen = (x**2 for x in range(5))
for num in gen:
print(num)
# 输出:
# 0
# 1
# 4
# 9
# 16
总结
Python 的类机制提供了强大的面向对象编程支持,使代码组织、复用和扩展变得更加容易。通过理解和掌握以下关键点,可以高效地使用类来构建复杂的应用程序:
- 名称和对象:理解名称与对象的关系,掌握作用域和命名空间的概念。
- 类的定义与实例化:使用
class
关键字定义类,通过构造方法__init__
初始化实例属性。 - 类和实例变量:区分类变量与实例变量,理解它们的共享和独立性。
- 方法对象:掌握实例方法、类方法和静态方法的定义与使用。
- 继承与多重继承:通过继承实现代码复用,理解方法解析顺序(MRO)。
- 私有变量:通过命名约定和
property
控制属性的访问权限,增强封装性。 - 迭代器与生成器:实现迭代器协议,使用生成器简化迭代器创建。
- 高级特性:如描述符、属性、动态添加属性和方法等,提升类的灵活性和功能性。
理解并灵活运用这些类的特性和方法,能够显著提升 Python 程序的组织性、可维护性和功能性。