6.6 KiB
6.6 KiB
类的组成成员分类
Python 类的组成成员可以分为三大类:字段(变量)、方法(函数)和属性(特殊方法),它们的定义方式、作用域和调用规则各有不同。
字段(变量)
字段分为实例变量和类变量,核心区别在于存储位置和作用对象:
- 实例变量:每个对象独立拥有一份实例变量,修改不影响其他对象。
- 类变量:通过类名或实例均可访问,但通过实例修改会创建同名实例变量,覆盖类变量。
示例:
class Dog:
species = "Canis lupus" # 类变量
def __init__(self, name):
self.name = name # 实例变量
d = Dog("Buddy")
print(d.name)
d1 = Dog()
print(Dog.species)
d1.species = "Mutt"
print(Dog.species)
方法(函数)
方法分为实例方法、类方法和静态方法,区别在于参数和调用方式:
- 实例方法:第一个参数为 self,指向调用该方法的实例;必须通过对象调用,可访问实例变量和类变量。
- 类方法:使用 @classmethod 装饰器,参数为 cls(指向类本身);操作类变量或实现工厂模式(创建实例)。
- 静态方法:使用 @staticmethod 装饰器,无默认参数,不依赖类或实例状态;执行与类相关的工具函数。
示例:
class Dog:
species = "Canis lupus" # 类变量
def __init__(self, name, age=0):
self.name = name # 实例变量
self.age = age
def bark(self):
print(f"{self.name} is barking!")
@classmethod
def create_from_string(cls, s):
name, age = s.split(",")
return cls(name, int(age)) # 创建实例时调用__init__方法
@classmethod
def get_species(cls):
return cls.species
@staticmethod
def describe():
return "Dogs are domesticated animals."
d = Dog("Buddy", 11)
d.bark() # Buddy is barking!
d1 = Dog.create_from_string("Max,5") # 通过类方法创建实例
d2 = Dog("Bella", 3) # 通过类方法创建实例
print(d2.name)
print(d1.age)
print(Dog.get_species()) # 类方法调用
d3 = Dog("Charlie", 2)
print(d3.get_species()) # 实例调用
print(Dog.describe()) # 静态方法调用
属性(Property)
属性是伪装成字段的方法,通过 @property 装饰器实现,用于封装逻辑。
class BankAccount:
def __init__(self, balance):
self.__balance = balance
@property
def balance(self):
return self.__balance
@balance.setter
def balance(self, value):
if value >= 0:
self.__balance = value
@balance.deleter
def balance(self):
del self.__balance
account = BankAccount(100)
print(account.balance) # 调用getter方法
account.balance = 200 # 调用setter方法
del account.balance # 删除属性
print(account.balance)
其他特殊成员
- 魔术方法:如
__init__
(构造函数)、__str__
(字符串表示)等,用于自定义类的行为。 - 私有成员:通过双下划线前缀(如 __variable)实现封装,仅在类内部访问。
示例:
class MyClass:
def __init__(self, value):
self.value = value # 公有属性
self.__value = value # 私有属性
def public_method(self):
return f'这是类的公有方法, value: {self.value}'
def __private_method(self):
return f'这是类的私有方法, value: {self.__value}'
def get_value(self):
return self.__value # 通过公有方法访问私有属性
obj = MyClass(10)
print(obj.value) # 访问公有属性
print(obj.public_method()) # 调用公有方法
print(obj.__value) # 访问公有属性
print(obj.__private_method()) # 调用私有方法
案例
需求
- 设计一个
Game
类 - 属性:
- 定义一个类属性
top_score
记录游戏的历史最高分 - 定义一个实例属性
player_name
记录当前游戏的玩家姓名
- 定义一个类属性
- 方法:
- 静态方法
show_help
显示游戏帮助信息 - 类方法
show_top_score
显示历史最高分 - 实例方法
start_game
开始当前玩家的游戏
- 静态方法
- 主程序步骤
- 查看帮助信息
- 查看历史最高分
- 创建游戏对象,开始游戏
class Game(object):
# 游戏最高分,类属性
top_score = 0
@staticmethod
def show_help():
print("帮助信息:让僵尸走进房间")
@classmethod
def show_top_score(cls):
print("游戏最高分是 %d" % cls.top_score)
def __init__(self, player_name):
self.player_name = player_name
def start_game(self):
print("[%s] 开始游戏..." % self.player_name)
# 使用类名.修改历史最高分
Game.top_score = 999
# 1. 查看游戏帮助
Game.show_help()
# 2. 查看游戏最高分
Game.show_top_score()
# 3. 创建游戏对象,开始游戏
game = Game("小明")
game.start_game()
# 4. 游戏结束,查看游戏最高分
Game.show_top_score()
总结
特性 | 普通方法 | 类方法 | 静态方法 |
---|---|---|---|
定义方式 | 不需要装饰器 | @classmethod |
@staticmethod |
第一个参数 | self |
cls |
无 |
访问权限 | 访问实例属性和方法 | 访问类属性和方法 | 无法访问类和实例属性 |
调用方式 | 通过实例调用 | 通过类或实例调用 | 通过类或实例调用 |
适用场景 | 实例相关操作 | 与类相关的操作 | 与类无关的操作 |
isinstace 与 issubclass
isinstance(a,b):判断a是否是b类(或者b类的派生类)实例化的对象
class A:
pass
class B(A):
pass
obj = B()
print(isinstance(obj,B))
print(isinstance(obj,A))
issubclass(a,b): 判断a类是否是b类(或者b的派生类)的派生类
class A:
pass
class B(A):
pass
class C(B):
pass
print(issubclass(B,A))
print(issubclass(C,A))
思考:那么 list str tuple dict等这些类与 Iterble类 的关系是什么?
from collections import Iterable
print(isinstance([1,2,3], list)) # True
print(isinstance([1,2,3], Iterable)) # True
print(issubclass(list, Iterable)) # True
# 由上面的例子可得,这些可迭代对象,list str tuple dict等 都是 Iterable 的子类。