Python学习笔记-面向对象篇
组合
class Engine:
"""引擎类,提供基本的引擎功能"""
def __init__(self, power):
self.power = power
def start(self):
print(f"引擎启动,功率:{self.power}")
class Car:
"""汽车类,使用引擎类的功能"""
def __init__(self, engine, color):
self.engine = engine # 引擎组合
self.color = color
def start_car(self):
self.engine.start() # 使用引擎的start方法
# 创建一个Engine实例
engine = Engine(200)
# 创建一个Car实例,并使用Engine实例
car = Car(engine, "红色")
# 启动汽车,实际上是启动引擎
car.start_car()
绑定
class MyClass:
def __init__(self, value):
self.attribute = value
obj = MyClass(10)
print(obj.attribute) # 输出: 10
# 在类定义外部进行绑定通常是指给实例添加新的属性。
class MyClass:
pass
obj = MyClass()
obj.new_attribute = 20
print(obj.new_attribute) # 输出: 20
MRO:方法解析顺序
class A:
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
print(D.mro()) # 输出:[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
多态
class Animal:
def speak(self):
raise NotImplementedError("子类必须实现该方法")
class Dog(Animal):
def speak(self):
return "汪汪汪"
class Cat(Animal):
def speak(self):
return "喵喵喵"
def animal_speaks(animal):
"""接受所有Animal类的子类实例,并调用它们的speak方法"""
print(animal.speak())
# 使用示例
dog = Dog()
cat = Cat()
animal_speaks(dog) # 输出: 汪汪汪
animal_speaks(cat) # 输出: 喵喵喵
鸭子类型
class Duck:
def quack(self):
print("Quack")
class Person:
def quack(self):
print("I am quacking like a duck!")
def perform_quack(duck):
duck.quack()
duck = Duck()
perform_quack(duck) # 输出: Quack
person = Person()
perform_quack(person) # 输出: I am quacking like a duck!
私有变量
class MyClass:
def __init__(self):
self.__private_var = 123 # 私有变量
def get_private_var(self): # 提供一个公共方法来获取私有变量的值
return self.__private_var
def update_private_var(self, value): # 提供一个公共方法来更新私有变量的值
self.__private_var = value
obj = MyClass()
# print(obj.__private_var) # AttributeError
print(obj.get_private_var()) # 输出: 123
obj.update_private_var(456)
print(obj.get_private_var()) # 输出: 456
下划线
# _xx:以单下划线开头,表示这是一个保护成员,只有类对象和子类对象自己能访问到这些变量。以单下划线开头的变量和函数被默认当作是内部函数,使用from module improt *时不会被获取,但是使用import module可以获取
# __xx:双下划线开头,表示为私有成员,只允许类本身访问,子类也不行。在文本上被替换为_class__method 或者 _class__变量名
# __xx__:双下划线开头,双下划线结尾。一种约定,Python内部的名字,用来区别其他用户自定义的命名,以防冲突。是一些 Python 的“魔术”对象,表示这是一个特殊成员
# xx_:以单下划线结尾仅仅是为了区别该名称与关键词
slots属性
# Python中的__slots__是一种优化机制,它限制了类实例能够添加的属性。使用__slots__主要是为了节省内存,尤其是当你有大量实例且具有相同的属性时。继承来自父类的slots属性在子类中不生效。
class Person:
__slots__ = ['name', 'age']
def __init__(self, name, age):
self.name = name
self.age = age
# 创建实例
p = Person('Alice', 30)
p.name = 'Bob' # 允许
p.score = 100 # 会抛出AttributeError,因为没有在__slots__中定义
内省
# dir([object]):返回对象的属性列表。如果没有提供参数,则返回当前范围内的变量、方法和定义的类。
class Person:
def __init__(self, name):
self.name = name
p = Person('Alice')
print(dir(p)) # 输出对象p的属性列表
# type(object):返回对象的类型。
print(type(42)) # 输出:<class 'int'>
# hasattr(object, name):检查对象是否有指定的属性。
class Person:
def __init__(self, name):
self.name = name
p = Person('Alice')
print(hasattr(p, 'name')) # 输出:True
# getattr(object, name[, default]):返回对象指定的属性值,如果属性不存在,则返回默认值。
class Person:
def __init__(self, name):
self.name = name
p = Person('Alice')
print(getattr(p, 'name', 'default')) # 输出:'Alice'
print(getattr(p, 'age', 'default')) # 输出:'default'
# setattr(object, name, value):设置对象指定的属性值。
class Person:
def __init__(self, name):
self.name = name
p = Person('Alice')
setattr(p, 'name', 'Bob')
print(p.name) # 输出:'Bob'
# delattr(object, name):删除对象指定的属性。
class Person:
def __init__(self, name):
self.name = name
p = Person('Alice')
delattr(p, 'name')
print(p.name) # 抛出AttributeError
# isinstance(object, classinfo):检查对象是否是指定类的实例。
class Person:
pass
p = Person()
print(isinstance(p, Person)) # 输出:True
# issubclass(class, classinfo):检查类是否是指定的基类的子类。
class Person:
pass
class Student(Person):
pass
print(issubclass(Student, Person)) # 输出:True
# 模块对象主要的元数据如下表:
元数据 含义说明
__name__ 模块名
__doc__ 模块的文档注释
__file__ 源文件名(包含路径)
__dict__ 包含了模块里可用的属性名-属性的字典;也就是可以使用模块名.属性名访问的对象。
# 函数对象主要的元数据如下表:
元数据 含义说明
__name__ 函数名
__doc__ 函数的文档注释
__module__ 函数所在的模块名,如果是入口模块会被重置为__main__
__defaults__ 默认位置参数的值元组。
__kwdefaults__ 按名的默认参数的值元组
__code__ 代码对象,函数的主代码
__class__ 指向函数对象类型
# 类的元数据如下表:
元数据 含义说明
__name__ 类名
__doc__ 类的文档注释
__module__ 类所在的模块名,注意如果是入口模块,显示的是__main__模块
__bases__ 父类元组
__dict__ 类对象的所有属性信息用字典的方式表示
# 实例(也就是类的对象)元数据如下表:
元数据 含义说明
__doc__ 类的文档注释
__class__ 指向类对象
__dict__ 对象的属性,包括私有属性,注意私有属性的命名方式
# 对象方法是特殊的函数,它有函数的全部元数据,也有自己特有的元数据如下表:
元数据 含义说明
__name__ 函数名
__doc__ 函数的文档注释
__module__ 函数所在的模块名,如果是入口模块会被重置为__main__
__defaults__ 默认位置参数的值元组。
__kwdefaults__ 按名的默认参数的值元组
__code__ 代码对象,函数的主代码
__class__ 指向函数对象类型
__self__ 方法特有的属性:指向实例对象
__func__ 方法特有的属性:指向函数对象自己
混入类
class LoggerMixin:
def log(self, message):
print(f"[LOG]: {message}")
class DataProcessor(LoggerMixin):
def process_data(self, data):
self.log("Starting data processing")
# 数据处理逻辑
processed_data = data * 2 # 简单的数据处理示例
self.log("Data processing completed")
return processed_data
class AnotherClass(LoggerMixin):
def perform_action(self):
self.log("Performing an action in AnotherClass")
# 使用混入类的DataProcessor
processor = DataProcessor()
result = processor.process_data(10)
print(f"Processed Data: {result}")
# 使用混入类的AnotherClass
another_instance = AnotherClass()
another_instance.perform_action()
魔术方法
魔术方法:对象的创建、初始化和销毁过程
# __new__、__init__、__del__
class Person:
def __new__(cls, *args, **kwargs):
print("Creating a new instance...")
instance = super().__new__(cls)
return instance
def __init__(self, name, age):
print("Initializing Person object...")
self.name = name
self.age = age
def __del__(self):
print(f"Deleting {self.name}...")
p = Person("Alice", 30)
print(f"Created {p.name}, age {p.age}")
del p
魔术方法:对象字符串描述
# __repr__、__str__
# 如果只定义了 __str__ 方法,而没有定义 __repr__ 方法,则在 repr(p) 中会调用 str(p) 的结果
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})" # 完整、详细的表示形式
def __str__(self):
return f"({self.x}, {self.y})" # 简洁、友好的表示形式
p = Point(3, 4)
print(repr(p)) # 输出: Point(3, 4)
print(str(p)) # 输出: (3, 4)
魔术方法:对象的比较运算
# __lt__、__gt__、__eq__、__ne__、__le__、__ge__
class MyNumber:
def __init__(self, value):
self.value = value
def __lt__(self, other):
return self.value < other.value
def __gt__(self, other):
return self.value > other.value
def __eq__(self, other):
return self.value == other.value
def __ne__(self, other):
return self.value != other.value
def __le__(self, other):
return self.value <= other.value
def __ge__(self, other):
return self.value >= other.value
a = MyNumber(10)
b = MyNumber(20)
print(a < b) # 输出: True
print(a > b) # 输出: False
print(a == b) # 输出: False
print(a != b) # 输出: True
print(a <= b) # 输出: True
print(a >= b) # 输出: False
魔术方法:对象其他常见运算
# __add__、__len__、__contains__、__bool__
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __len__(self):
return abs(self.x) + abs(self.y)
def __contains__(self, item):
return item == self.x or item == self.y
def __bool__(self):
return self.x != 0 or self.y != 0
v1 = Vector(3, 4)
v2 = Vector(1, 2)
v3 = v1 + v2
print(v3) # 输出: Vector(4, 6)
print(len(v3)) # 输出: 10
print(3 in v3) # 输出: True
print(5 in v3) # 输出: False
print(bool(v1)) # 输出: True
print(bool(Vector(0, 0))) # 输出: False
魔术方法:对象的属性管理
# __getattr__、__setattr__、__delattr__
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __getattr__(self, name):
print(f"Getting attribute '{name}'")
raise AttributeError(f"'Person' object has no attribute '{name}'")
def __setattr__(self, name, value):
print(f"Setting attribute '{name}' to '{value}'")
super().__setattr__(name, value)
def __delattr__(self, name):
print(f"Deleting attribute '{name}'")
super().__delattr__(name)
p = Person("Alice", 30)
print(p.age) # 输出: 30
p.age = 31 # 输出: Setting attribute 'age' to '31'
del p.age # 输出: Deleting attribute 'age'
print(p.address) # 输出: Getting attribute 'address',抛出 AttributeError
魔术方法:对象的索引管理
# __getitem__、__setitem__、__delitem__
class MySequence:
def __init__(self, *args):
self.data = list(args)
def __repr__(self):
return repr(self.data)
def __getitem__(self, index):
return self.data[index]
def __setitem__(self, index, value):
self.data[index] = value
def __delitem__(self, index):
del self.data[index]
def __len__(self):
return len(self.data)
def append(self, value):
self.data.append(value)
def insert(self, index, value):
self.data.insert(index, value)
def pop(self, index=-1):
return self.data.pop(index)
seq = MySequence(1, 2, 3, 4, 5)
print(seq[2]) # 输出: 3
seq[1] = 10
print(seq) # 输出: [1, 10, 3, 4, 5]
del seq[3]
print(seq) # 输出: [1, 10, 3, 5]
seq.append(6)
print(seq) # 输出: [1, 10, 3, 5, 6]
print(len(seq)) # 输出: 5
魔术方法:with语句上下文管理器
# __enter__、__exit__
class DatabaseConnection:
def __enter__(self):
print("数据库连接已打开")
# 这里可以添加打开数据库的代码
return self
def __exit__(self, exc_type, exc_value, traceback):
print("数据库连接已关闭")
# 这里可以添加关闭数据库的代码
if exc_type is None:
return False
with DatabaseConnection() as db:
print(f"正在使用数据库: {db}")
魔术方法:对象的迭代
# __iter__、__next__
class Person:
def __init__(self, name, age, city):
self.attributes = {'name': name, 'age': age, 'city': city}
self.keys = iter(self.attributes)
def __iter__(self):
return self
def __next__(self):
key = next(self.keys)
return key, self.attributes[key]
person = Person('Alice', 30, 'New York')
for attr, value in person:
print(f'{attr}: {value}')
魔术方法:允许对象像函数一样被调用
# __call__
class Counter:
def __init__(self):
self.count = 0
def __call__(self):
self.count += 1
return self.count
counter = Counter()
print(counter()) # 输出: 1
print(counter()) # 输出: 2
print(counter()) # 输出: 3
contextmanager上下文管理器
from contextlib import contextmanager
class DatabaseConnection:
def __init__(self):
self.connected = False
def connect(self):
self.connected = True
print("Database connected")
def disconnect(self):
self.connected = False
print("Database disconnected")
@contextmanager
def manage_db_connection():
db = DatabaseConnection()
db.connect()
try:
yield db
finally:
db.disconnect()
with manage_db_connection() as db:
print(f'Using database: {db.connected}')
property定义属性
class C:
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
# 使用例子
c = C()
c.x = 10
print(c.x) # 输出: 10
del c.x
try:
print(c.x)
except AttributeError as e:
print(e) # 输出: 'C' object has no attribute '_x'
类方法和静态方法
class MyClass:
'''
类方法接收类作为它的第一个参数,通常以cls作为前缀。静态方法则不接受任何特殊参数,可以看作是全局函数。 这两种方法都可以通过类直接调用,无需创建类的实例。
'''
@classmethod
def class_method(cls):
print(f"This is a class method. Class: {cls.__name__}")
@staticmethod
def static_method():
print("This is a static method.")
MyClass.class_method() # 不需要实例化
MyClass.static_method() # 同样不需要实例化
描述符协议
class MyDescriptor:
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
print(f"Getting {self.name}")
return instance.__dict__[self.name]
def __set__(self, instance, value):
print(f"Setting {self.name}")
instance.__dict__[self.name] = value
def __delete__(self, instance):
print(f"Deleting {self.name}")
instance.__dict__.pop(self.name)
class MyClass:
x = MyDescriptor('x')
obj = MyClass()
obj.x = 10 # 触发 __set__,输出 :Setting x
print(obj.x) # 触发 __get__,输出 :Getting x 10
del obj.x # 触发 __delete__,输出 :Deleting x
类装饰器
def decorator(cls):
"""
# 定义了一个装饰器函数 decorator,它接受一个类作为参数,并返回一个新的被装饰过的子类。
# 当这个装饰器被应用到 MyClass 类上时,它会创建一个新的继承自 MyClass 的内部类 DecoratedClass, # 并且在其 __init__ 方法中打印一条消息。
# 这展示了如何在不修改原始类定义的情况下,给类添加额外的初始化行为。
"""
class DecoratedClass(cls):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print("类已被装饰器装饰。")
return DecoratedClass
@decorator # 等同于 MyClass = decorator(MyClass)
class MyClass:
def __init__(self):
print("类初始化。")
my_object = MyClass()
__init_subclass__函数
class A:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
# 这里可以添加更多的初始化子类的代码
print(f"初始化了子类: {cls.__name__}")
# 使用 A 作为基类创建子类时,会自动调用 __init_subclass__ 方法
class B(A):
pass
# 输出: 初始化了子类: B
元类
# 给所有的子类对象增加一个作者的属性
class MetaClass(type):
def __new__(mcls, name, bases, attrs):
# 在这里,我们给类添加一个author属性
attrs["author"]= "John Doe"
return type.__new__(mcls, name, bases, attrs)
class AuthorizedClass(metaclass=MetaClass):
pass
class SubClass(AuthorizedClass):
pass
s = SubClass()
print(s.author) # 输出: John Doe
#############################################
class MetaClass(type):
def __init__(cls, name, bases, attrs):
# 在这里,我们给类添加一个author属性
cls.author= "John Doe"
return type.__init__(cls, name, bases, attrs)
class AuthorizedClass(metaclass=MetaClass):
pass
class SubClass(AuthorizedClass):
pass
s = SubClass()
print(s.author)
# 规范类名
class MetaClass(type):
def __init__(cls, name, bases, attrs):
if not name.istitle():
raise TypeError("类名称不符合规范")
return type.__init__(cls, name, bases, attrs)
class Subclass(metaclass=MetaClass): # 正常创建
pass
class SubClass(metaclass=MetaClass): # 发生异常
pass
# 只支持关键字传参
class MetaClass(type):
def __call__(cls, *args, **kwargs):
if args:
raise TypeError("只支持关键字参数")
return type.__call__(cls, *args, **kwargs)
class SubClass(metaclass=MetaClass):
def __init__(self, name):
self.name = name
s = SubClass(name="John") # 正常创建
s = SubClass("John") # 发生异常
# 类禁止被实例化
class MetaClass(type):
def __call__(cls, *args, **kwargs):
raise TypeError("该类不允许直接实例化对象")
class SubClass(metaclass=MetaClass):
pass
c = SubClass() # 发生异常
# 只允许实例化一个对象
class MetaClass(type):
def __init__(cls, name, bases, attrs):
cls.__instance = None
return type.__init__(cls, name, bases, attrs)
def __call__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = type.__call__(cls, *args, **kwargs)
return cls.__instance
else:
return cls.__instance
class SubClass(metaclass=MetaClass):
pass
c1 = SubClass()
c2 = SubClass()
c1 is c2 # 输出:True
print(dir(SubClass))
抽象基类
import abc
class AbstractClass(metaclass=abc.ABCMeta):
@abc.abstractmethod
def abstract_method(self):
pass
@abc.abstractmethod
def another_abstract_method(self):
pass
# 下面的代码将会抛出错误,因为ConcreteClass没有实现所有的抽象方法
# concrete_instance = AbstractClass()
class ConcreteClass(AbstractClass):
def abstract_method(self):
print('实现了abstract_method方法')
def another_abstract_method(self):
print('实现了another_abstract_method方法')
# 这样就可以正常创建实例了
concrete_instance = ConcreteClass()
作者:wanghongwei
版权声明:本作品遵循<CC BY-NC-ND 4.0>版权协议,商业转载请联系作者获得授权,非商业转载请附上原文出处链接及本声明。