Python面向对象
大约 4 分钟
面向对象
类提供了把数据和功能绑定在一起的方法,类的实例化会创建一个新的对象,每个对象都有自己的属性和方法。
名称与对象
对象之间相互独立,多个名称(甚至是多个作用域内的多个名称)可以绑定到同一对象。
# 赋值不会拷贝对象,只是让多个名称指向同一个对象
a = [1, 2, 3]
b = a # b和a绑定的是同一个列表
b.append(4)
print(a) # [1, 2, 3, 4],通过b修改,a也"变"了
print(a is b) # True,is判断两个名称是否指向同一个对象
# 想要独立的副本,需创建新对象(切片是浅拷贝)
c = a[:]
c.append(5)
print(a) # [1, 2, 3, 4],不受c影响
print(c) # [1, 2, 3, 4, 5]
Python 作用域和命名空间
命名空间是一个从名称到对象的映射。在 Python 中,每个模块、类或函数都有自己的命名空间。命名空间的作用是避免名称冲突,使代码更加清晰和可维护。
类的定义
class MyClass:
"""一个简单的类示例"""
i = 12345
def f(self):
return 'hello world'
类属性与方法
# 类:类提供了把数据和功能绑定在一起的方法
# 作用域
def scope_test():
def do_local():
spam = "local spam"
def do_nonlocal():
nonlocal spam # nonlocal:声明为最近外层的局部变量
spam = "nonlocal spam"
def do_global():
global spam # global:声明为全局变量
spam = "global spam"
spam = "test spam"
do_local()
print("After local assignment:", spam) # test spam
do_nonlocal()
print("After nonlocal assignment:", spam) # nonlocal spam
do_global()
print("After global assignment:", spam) # nonlocal spam
scope_test()
print("In global scope:", spam) # global spam
# 类
class Animal:
# 颜色:公共属性,会被所有子对象共用
colors = []
# 赋初始值,类似于js中的constructor
def __init__(self, name):
self.name = name
self.skills = [] # 每个实例独有属性
def set_name(self, name):
self.name = name
def get_name(self):
return self.name
# 添加颜色
def set_color(self, color):
self.colors.append(color)
# 添加能力
def set_skill(self, skill):
self.skills.append(skill)
# 间隔符号
def add_logs(self):
print("-------------")
# 调用自身函数
def classTest(self):
self.add_logs()
# 创建dog实例
dog = Animal("Dog")
dog.set_name("旺财")
dog.set_skill("汪汪汪")
print(dog.get_name()) # 旺财
print(dog.skills) # ['汪汪汪']
# 创建cat实例
cat = Animal("Cat")
cat.set_name("Tom")
cat.set_color("orange")
print(dog.colors) # ['orange']
print(cat.colors) # ['orange']
cat.set_skill("喵喵喵")
print(cat.skills) # ['喵喵喵']
cat.classTest()
类继承
# 继承
class Device:
def __init__(self, device_name, device_code):
self.device_name = device_name
self.device_code = device_code
def get_device_info(self):
return {
"device_name": self.device_name,
"device_code": self.device_code
}
class EMS(Device): # 继承Device类
def __init__(self, device_name, device_code):
super().__init__(device_name, device_code)
def set_ems_power(self, power):
self.ems_power = power
ems = EMS('EMS', 'EMS-0001')
device_info = ems.get_device_info()
print(device_info)
多继承:class Son(Father1, Father2),按括号中的顺序查找属性和方法(MRO 顺序);子类重写父类方法后,仍可通过 super() 调用父类的原实现。
类方法与静态方法
class DateTools:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
# 实例方法:第一个参数是实例self,可以访问实例属性
def show(self):
print(f"{self.year}-{self.month}-{self.day}")
# 类方法:第一个参数是类cls,常用作替代构造函数
@classmethod
def from_string(cls, date_str):
year, month, day = map(int, date_str.split('-'))
return cls(year, month, day) # cls()等价于DateTools()
# 静态方法:既不接收实例也不接收类,就是一个放在类命名空间下的普通函数
@staticmethod
def is_valid(date_str):
parts = date_str.split('-')
return len(parts) == 3 and all(p.isdigit() for p in parts)
d = DateTools.from_string('2026-09-16') # 类方法创建实例
d.show() # 2026-9-16
print(DateTools.is_valid('2026-09-16')) # True
常用魔术方法
魔术方法(双下划线方法)由 Python 在特定时机自动调用,用于自定义对象的行为。
class Book:
def __init__(self, title, price):
self.title = title
self.price = price
# print(对象) 时的显示内容
def __str__(self):
return f"《{self.title}》¥{self.price}"
# 面向开发者的调试显示,str不存在时的兜底
def __repr__(self):
return f"Book(title={self.title!r}, price={self.price})"
# 两个对象使用 == 比较时调用
def __eq__(self, other):
return isinstance(other, Book) and self.title == other.title
# len(对象) 时调用
def __len__(self):
return len(self.title)
book1 = Book("Python从入门到实践", 89)
book2 = Book("Python从入门到实践", 65)
print(book1) # 《Python从入门到实践》¥89
print(repr(book2)) # Book(title='Python从入门到实践', price=65)
print(book1 == book2) # True,只比较了书名
print(len(book1)) # 12
私有变量
python中不存在私有属性,但是可以通过约定来定义。
# 私有属性:仅限从一个对象内部访问的“私有”实例变量在 Python 中并不存在。Python 代码都遵循这样一个约定:带有一个下划线的名称 (例如 _spam) 应该被当作是非公有部分
class Bird:
def __init__(self, name, age):
self.name = name
self.age = age
self._colors = [] # 遵守约定,_colors为私有属性,同理,函数也一致
def set_color(self, color):
self._colors.append(color)
bird1 = Bird("Bird1", "Bird-0001")
bird1.set_color("blue")
print(bird1._colors)
bord2 = Bird("Bord2", "Bord-0002")
bord2.set_color("red")
print(bord2._colors)
双下划线开头的属性(例如
__name)会触发「名称改写」(name mangling),实际存储为_类名__name,子类不易直接访问,但依然不是真正的私有。
property:把方法伪装成属性
@property 让方法像属性一样访问,可以在设置值时做校验,调用方无感知。
class Account:
def __init__(self):
self._balance = 0
@property
def balance(self):
return self._balance
# 设置balance时自动校验
@balance.setter
def balance(self, value):
if value < 0:
raise ValueError("余额不能为负数")
self._balance = value
account = Account()
account.balance = 100 # 像属性一样赋值,实际走setter校验
print(account.balance) # 100,像属性一样读取
Loading...
