类
类(class)
类是创建对象的蓝图或模板,它定义了对象应该具有的属性和方法。
基本语法
class ClassName:
"""类的文档"""
def __init__(self):
pass
注意: 类名通常使用帕斯卡命名法(PascalCase),即每个单词的首字母大写。
类变量(Class Variables)
类变量是属于整个类的变量,被该类的所有实例共享。
class Dog:
# 类变量 - 所有狗都共享这个属性
species = "Canis lupus"
total_dogs = 0 # 统计创建了多少只狗
def __init__(self, name):
self.name = name
Dog.total_dogs += 1 # 每创建一个实例,类变量增加1
# 测试类变量
dog1 = Dog("小白")
dog2 = Dog("小黑")
print(Dog.species) # 输出: Canis lupus
print(Dog.total_dogs) # 输出: 2
print(dog1.species) # 实例也可以访问类变量
重要: 类变量可以通过类名直接访问,也可以通过实例访问,但修改时要小心!
实例变量(Instance Variables)
实例变量是属于特定对象实例的变量,每个实例都有自己独立的实例变量。
class Person:
def __init__(self, name, age, city):
# 这些都是实例变量
self.name = name
self.age = age
self.city = city
def introduce(self):
return f"我是{self.name},{self.age}岁,住在{self.city}"
# 创建不同的实例
person1 = Person("张三", 25, "北京")
person2 = Person("李四", 30, "上海")
print(person1.introduce()) # 我是张三,25岁,住在北京
print(person2.introduce()) # 我是张三,25岁,住在北京
关键点: 实例变量在
__init__
方法中通过self.variable_name
定义,每个实例都有自己的副本。
getter && setter —— 属性装饰器
使用
@property
装饰器实现getter
使用
@celsius.setter
装饰器实现setter
class Temperature:
def __init__(self, celsius=0):
self._celsius = celsius
@property
def celsius(self):
"""获取摄氏度"""
return self._celsius
@celsius.setter
def celsius(self, value):
"""设置摄氏度"""
if value < -273.15:
raise ValueError("温度不能低于绝对零度")
self._celsius = value
@property
def fahrenheit(self):
"""计算华氏度(只读)"""
return self._celsius * 9/5 + 32
# 使用属性
temp = Temperature(25)
print(f"摄氏度: {temp.celsius}°C") # 25°C
print(f"华氏度: {temp.fahrenheit}°F") # 77.0°F
# 修改温度
temp.celsius = 30
print(f"新温度: {temp.celsius}°C") # 30°C
实例方法(Instance Methods)
self
不是Python关键字,而是一个约定俗成的参数名,代表当前对象实例本身。
实例方法的第一个参数必须是 self
,用于操作实例数据
class Calculator:
def __init__(self, initial_value=0):
self.value = initial_value # self指向当前创建的实例
# 实例方法 - 增加数量
def add(self, num):
self.value += num # 修改当前实例的value
return self # 返回自身,支持链式调用
# 实例方法 - 乘以数量
def multiply(self, num):
self.value *= num
return self
# 实例方法 - 获取结果
def get_result(self):
return self.value
# 使用示例
calc = Calculator(10)
result = calc.add(5).multiply(2).get_result()
print(result) # 输出: 30
重要提醒: 虽然可以用其他名字代替
self
,但强烈建议使用self
,这是Python社区的约定。
类方法(Class Methods)
类方法使用@classmethod
装饰器,第一个参数是cls
(代表类本身),主要用于操作类变量或创建实例的替代方法。
class Employee:
company_name = "科技有限公司"
employee_count = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.employee_count += 1
@classmethod
def get_company_info(cls):
"""获取公司信息 - 类方法"""
return f"公司: {cls.company_name}, 员工总数: {cls.employee_count}"
@classmethod
def set_company_name(cls, new_name):
"""修改公司名称 - 类方法"""
cls.company_name = new_name
@classmethod
def from_string(cls, employee_string):
"""从字符串创建员工对象 - 替代构造方法"""
name, salary = employee_string.split('-')
return cls(name, int(salary))
def get_info(self):
return f"员工: {self.name}, 工资: {self.salary}"
# 使用类方法
print(Employee.get_company_info()) # 可以直接通过类调用
# 使用替代构造方法
emp1 = Employee.from_string("张三-8000")
emp2 = Employee("李四", 9000)
print(emp1.get_info()) # 员工: 张三, 工资: 8000
print(Employee.get_company_info()) # 公司: 科技有限公司, 员工总数: 2
# 修改公司名称
Employee.set_company_name("新科技有限公司")
print(Employee.get_company_info()) # 公司: 新科技有限公司, 员工总数: 2
使用场景: 类方法常用于工厂方法模式(创建对象的替代方法)和操作类级别的数据。s
静态方法(Static Methods)
静态方法使用@staticmethod
装饰器,不需要self
或cls
参数,与类的实例无关,主要用于工具函数。
import math
from datetime import datetime
class MathUtils:
"""数学工具类"""
@staticmethod
def calculate_distance(x1, y1, x2, y2):
"""计算两点间的距离"""
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
@staticmethod
def is_prime(n):
"""判断是否为质数"""
if n < 2:
return False
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
@staticmethod
def factorial(n):
"""计算阶乘"""
if n <= 1:
return 1
return n * MathUtils.factorial(n - 1)
# 使用静态方法 - 可以直接通过类调用,不需要创建实例
distance = MathUtils.calculate_distance(0, 0, 3, 4)
print(f"距离: {distance}") # 距离: 5.0
print(f"17是质数吗? {MathUtils.is_prime(17)}") # True
print(f"5的阶乘: {MathUtils.factorial(5)}") # 120
关键特点: 静态方法独立于类的实例,可以看作是放在类中的普通函数,主要用于逻辑上与类相关但不需要访问实例或类数据的功能。
私有和公开(Private and Public)
Python使用命名约定来区分私有和公开属性,没有真正的私有性,主要依靠开发者遵守约定。
命名约定规则
命名方式 | 含义 | 访问性 |
---|---|---|
attribute | 公开属性 | 完全公开 |
_attribute | 受保护属性 | 内部使用,但可访问 |
__attribute | 私有属性 | 名称改写,难以直接访问 |
实际示例
class BankAccount:
def __init__(self, user_name, initial_balance, password):
self.user_name = user_name # 公开属性
self._balance = initial_balance # 受保护属性(约定内部使用)
self.__password = password # 私有属性(名称改写)
# 测试访问控制
account = BankAccount("kingmusi", 1000, '123')
# 公开属性 - 可以直接访问
print(account.user_name) # kingmusi
# 受保护属性 - 可以访问但不建议
print(account._balance) # 1000 (可以访问,但约定不要这样做)
# 私有属性 - 无法直接访问
try:
print(account.__password)
except AttributeError as e:
print(f"错误: {e}") # 'BankAccount' object has no attribute '__password'
# 但是可以通过名称改写访问(不建议)
print(account._BankAccount__password) # 123
方法也是同理的,想设置方法为私有方法,把方法名定义为
__
开头