0%

类和对象

Python 类和对象详解(Python 3.x)

Python 是一种面向对象的编程语言,类(Class)和对象(Object)是其核心概念。类是对象的模板,定义了对象的属性和方法;对象是类的实例,具有类所定义的特征和行为。本文将详细介绍 Python 中类和对象的创建、方法、变量、继承等核心特性。

类的定义与对象的创建

基本语法

使用 class 关键字定义类,类名通常采用帕斯卡命名法(首字母大写,如 Person)。通过类名加括号(无需 new 关键字)创建对象。

1
2
3
4
5
6
7
# 定义空类(pass 表示空代码块)
class Person:
pass

# 创建对象(实例化)
p = Person()
print(p) # 输出:<__main__.Person object at 0x...>(对象的内存地址)

类中的方法

类中的函数称为方法,与普通函数的区别是:方法的第一个参数必须是 self(表示对象自身,类似 Java 的 this)。调用方法时,self 由 Python 自动传递,无需手动传入。

1
2
3
4
5
6
7
8
9
class Person:
# 定义方法,第一个参数必须是 self
def say_hello(self):
print("Hello, I'm a Person!")

# 创建对象
p = Person()
# 调用方法(无需传递 self)
p.say_hello() # 输出:Hello, I'm a Person!

构造方法 __init__

__init__ 是 Python 的构造方法,用于对象初始化(创建对象时自动调用),相当于 Java 中与类名同名的构造函数。

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person:
# 构造方法:初始化对象的属性
def __init__(self, name, age):
# self.属性名:定义对象的实例属性
self.name = name
self.age = age

# 定义方法,使用实例属性
def introduce(self):
print(f"我叫 {self.name},今年 {self.age} 岁")

# 创建对象时传递参数(自动调用 __init__)
p = Person("Alice", 20)
p.introduce() # 输出:我叫 Alice,今年 20 岁

说明

  • __init__ 方法在对象创建时自动执行,用于初始化属性。
  • self.nameself.age 是对象的实例属性,每个对象都有独立的副本。

默认参数构造方法

__init__ 支持默认参数,使创建对象时部分参数可选:

1
2
3
4
5
6
7
8
9
10
11
12
class Student:
def __init__(self, name, major="计算机科学"): # major 有默认值
self.name = name
self.major = major

# 不传递 major,使用默认值
s1 = Student("Bob")
print(s1.major) # 输出:计算机科学

# 传递 major,覆盖默认值
s2 = Student("Charlie", "数学")
print(s2.major) # 输出:数学

类变量与实例变量

Python 中有两种变量:类变量(属于类,所有对象共享)和实例变量(属于对象,每个对象独立)。

实例变量

通过 self.变量名 定义,每个对象有独立的值,如 self.nameself.age

类变量

在类中直接定义(不在方法内),属于类本身,所有对象共享该变量。通过 类名.变量名self.类名.变量名 访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Employee:
# 类变量:所有员工共享,记录员工总数
emp_count = 0

def __init__(self, name):
# 实例变量:每个员工的姓名
self.name = name
# 访问类变量,每次创建对象时计数+1
Employee.emp_count += 1

def get_info(self):
print(f"姓名:{self.name},员工总数:{Employee.emp_count}")

# 创建两个对象
e1 = Employee("张三")
e2 = Employee("李四")

e1.get_info() # 输出:姓名:张三,员工总数:2
e2.get_info() # 输出:姓名:李四,员工总数:2
print(Employee.emp_count) # 输出:2(直接通过类名访问类变量)

区别

  • 实例变量:每个对象独立,如 e1.namee2.name 可以不同。
  • 类变量:所有对象共享,修改类变量会影响所有对象。

继承

继承是面向对象的核心特性,允许子类(派生类)继承父类(基类)的属性和方法,实现代码复用。Python 支持单继承和多继承。

单继承

语法:class 子类名(父类名):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 父类
class Animal:
def __init__(self, name):
self.name = name

def eat(self):
print(f"{self.name} 在吃东西")

# 子类(继承 Animal)
class Dog(Animal):
# 子类可以新增方法
def bark(self):
print(f"{self.name} 在汪汪叫")

# 创建子类对象
dog = Dog("旺财")
dog.eat() # 继承父类的方法 → 输出:旺财 在吃东西
dog.bark() # 子类自己的方法 → 输出:旺财 在汪汪叫

重写父类方法

子类可以重写父类的方法(包括 __init__),覆盖父类的实现:

1
2
3
4
5
6
7
8
9
10
11
12
class Cat(Animal):
# 重写父类的 eat 方法
def eat(self):
print(f"{self.name} 爱吃鱼")

# 新增方法
def meow(self):
print(f"{self.name} 在喵喵叫")

cat = Cat("咪咪")
cat.eat() # 输出:咪咪 爱吃鱼(调用重写后的方法)
cat.meow() # 输出:咪咪 在喵喵叫

调用父类方法

若子类重写了父类方法,可通过 super()父类名 调用父类的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Bird(Animal):
def __init__(self, name, can_fly):
# 调用父类的 __init__ 方法(初始化 name)
super().__init__(name) # 等价于 Animal.__init__(self, name)
self.can_fly = can_fly # 子类新增属性

# 重写父类方法,并调用父类逻辑
def eat(self):
super().eat() # 调用父类的 eat 方法
print(f"{self.name} 还爱吃虫子")

bird = Bird("麻雀", True)
bird.eat()
# 输出:
# 麻雀 在吃东西
# 麻雀 还爱吃虫子

super() 的作用

  • 在子类中调用父类的方法,避免硬编码父类名,增强代码可维护性。

多继承

Python 支持多继承(一个子类继承多个父类),语法:class 子类名(父类1, 父类2, ...):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 父类1
class Flyable:
def fly(self):
print("会飞")

# 父类2
class Swimmable:
def swim(self):
print("会游泳")

# 子类继承两个父类
class Duck(Flyable, Swimmable):
pass

duck = Duck()
duck.fly() # 输出:会飞(继承自 Flyable)
duck.swim() # 输出:会游泳(继承自 Swimmable)

注意:多继承可能导致菱形问题(多个父类继承自同一基类),需谨慎使用。Python 通过 MRO(方法解析顺序)机制解决冲突(多个父类具有相同方法的话,哪个父类在前边就用哪个的)。

内置属性__mro__可以查看方法搜索顺序

对象的属性访问控制

Python 没有严格的访问修饰符(如 Java 的 privatepublic),但可通过命名约定实现类似效果:

  • 公开属性:直接定义(如 self.name),可被外部访问。
  • 私有属性:命名以双下划线 __ 开头(如 self.__age),外部无法直接访问(实际是名称改写机制)。
1
2
3
4
5
6
7
8
9
10
11
12
13
class Person:
def __init__(self, name, age):
self.name = name # 公开属性
self.__age = age # 私有属性(外部无法直接访问)

# 提供公开方法访问私有属性
def get_age(self):
return self.__age

p = Person("Alice", 20)
print(p.name) # 输出:Alice(可直接访问公开属性)
# print(p.__age) # 报错:AttributeError(无法直接访问私有属性)
print(p.get_age()) # 输出:20(通过方法访问私有属性)

说明

  • 私有属性并非绝对不可访问,Python 会将 __age 改写为 _Person__age,外部可通过 p._Person__age 访问(不推荐)。
  • 命名约定的核心是 “约定优于配置”,提醒开发者不要随意修改私有属性。

常用的特殊方法

Python 类中以双下划线开头和结尾的方法(如 __init__)称为特殊方法(或魔术方法),用于实现对象的特殊行为。

特殊方法 作用 示例
__init__ 构造方法,初始化对象 def __init__(self, name): ...
__str__ 定义对象的字符串表示(str() def __str__(self): return self.name
__repr__ 定义对象的官方字符串表示 def __repr__(self): return f"Person({self.name})"
__len__ 定义 len(obj) 的行为 def __len__(self): return len(self.data)

示例:__str__ 方法

1
2
3
4
5
6
7
8
9
10
11
class Book:
def __init__(self, title, author):
self.title = title
self.author = author

# 定义对象的字符串表示
def __str__(self):
return f"《{self.title}》(作者:{self.author})"

book = Book("Python 编程", "张三")
print(book) # 输出:《Python 编程》(作者:张三)(自动调用 __str__)

欢迎关注我的其它发布渠道