MST
星途 面试题库

面试题:Python元类与继承、多态的协同设计优化

在复杂的Python项目中,元类、继承和多态可能需要协同工作来实现高效且灵活的代码设计。请描述一种场景,其中元类、继承和多态相互配合,解决项目中的关键问题。并详细说明如何设计元类来影响继承类的行为,以及多态在这个过程中是如何进一步增强代码的可复用性和可维护性的。
19.0万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

场景描述

假设我们正在开发一个游戏框架,其中需要创建各种类型的游戏角色,如战士、法师、刺客等。每个角色都有不同的行为和属性,但它们都继承自一个基类 Character。同时,我们希望通过元类来自动为每个角色类添加一些通用的功能,例如日志记录功能,记录角色的各种行为(如攻击、防御等)。

元类设计

import logging


class CharacterMeta(type):
    def __new__(mcs, name, bases, attrs):
        def log_action(func):
            def wrapper(self, *args, **kwargs):
                logging.info(f"{self.__class__.__name__} is performing {func.__name__}")
                return func(self, *args, **kwargs)

            return wrapper

        for attr_name, attr_value in attrs.items():
            if callable(attr_value) and not attr_name.startswith('__'):
                attrs[attr_name] = log_action(attr_value)
        return super().__new__(mcs, name, bases, attrs)


这个元类 CharacterMeta 会遍历类的属性,对于所有非特殊方法(不以 __ 开头),它会为这些方法添加日志记录功能。

继承与元类结合

class Character(metaclass=CharacterMeta):
    def __init__(self, name):
        self.name = name


class Warrior(Character):
    def attack(self):
        print(f"{self.name} the Warrior is attacking!")


class Mage(Character):
    def cast_spell(self):
        print(f"{self.name} the Mage is casting a spell!")


这里 WarriorMage 类继承自 Character 类,由于 Character 使用了 CharacterMeta 元类,所以 WarriorMage 的非特殊方法都会自动被添加日志记录功能。

多态增强可复用性和可维护性

在游戏框架中,我们可能有一个函数来处理角色的各种行为,例如:

def perform_action(character):
    if hasattr(character, 'attack'):
        character.attack()
    elif hasattr(character,'cast_spell'):
        character.cast_spell()


warrior = Warrior("Aragorn")
mage = Mage("Gandalf")

perform_action(warrior)
perform_action(mage)


多态在这里发挥了作用,perform_action 函数可以接受任何继承自 Character 的类的实例,而不需要关心具体是哪个子类。如果后续需要添加新的角色类型,只需要继承 Character 类并实现相应的方法,perform_action 函数无需修改就可以处理新的角色类型,增强了代码的可复用性。同时,如果需要修改日志记录的行为或者其他通用功能,只需要在元类中进行修改,所有继承自 Character 的子类都会自动受到影响,增强了代码的可维护性。