用于预定义类创建的元类与继承

     2023-02-23     302

关键词:

【中文标题】用于预定义类创建的元类与继承【英文标题】:Metaclass vs inheritance for predefined class creation 【发布时间】:2019-01-26 03:48:58 【问题描述】:

我正在为一个程序编写一些代码,该程序将能够运行一些软件、读取输入/输出并在此过程中进行一些数据处理。例如:(这不是真实情况,只是提供一个想法)

class MusicFile(object):
   extension = [""]

   def setup(self):
       #set up the data

   def runsoftware(self):
       #play the song

class MP3(MusicFile):
   extension = [".mp3"]

   def setup(self):
       #setupMP3file

   def runsoftware(self):
       #runMP3software

我有大约 4 个通用类,然后文件扩展名将被定义和处理不同。每个类都有其工作所需的定义数量的方法。目前,仅支持一个或两个文件扩展名,但我想保留一个结构,让其他人可以轻松地(也许是直观地)添加更多扩展名。

我从事编码工作的时间不长,我接到了这项任务,我希望以最好的方式完成这项任务。

元类的使用适合这种情况吗?为了设置一些必须包含我之前定义的方法的严格类,这样它将在所有这些类中保持一致。我应该坚持简单的继承吗?

我希望能够注册MusicFile 的所有子类,以便能够实例化正确的子类(例如,给定文件路径)。

我读过关于元类的文章,它们似乎很适合这种情况,但由于我也读过如果你不太了解它们就不需要使用它们,我想问一下征求您的专家意见。

【问题讨论】:

【参考方案1】:

此答案仅适用于 Python 3.6+。如果您可以选择升级到最新的 Python 版本,there are numerous reasons why you should 和以下可能就是其中之一。

Python 3.6 引入了__init_subclass__ 挂钩,该挂钩在类被子类化后执行。

class MusicFile:
    _register = 

    def __init_subclass__(cls, **kwargs):
        if not hasattr(cls, 'extension'):
            raise ValueError(cls.__name__ + ' has no extension')

        MusicFile._register.update(e: cls for e in cls.extension)

    @classmethod
    def get_class_by_extension(cls, ext):
        return cls._register.get(ext)

示例

class MP3(MusicFile):
    extension = ['mp3']

class MIDI(MusicFile):
    extension = ['midi']

MusicFile.get_class_by_extension('mp3') # <class '__main__.MP3'>
MusicFile.get_class_by_extension('midi') # <class '__main__.MIDI'>

请注意,这与the factory approach suggested by bipll 非常相似,但采用更直接和可维护的方式。

【讨论】:

【参考方案2】:

我希望能够注册 MusicFile 的所有子类,以便能够实例化正确的子类(例如,给定文件路径)。

所以你可能想要实现a Factory?

这个工厂可能可以用元类自动构建。我看到的一个严重问题是使用类自己的extension 成员来注册它,所以对我来说,元类的永恒竞争更容易完成,装饰器:

class MusicFile(object):
    known_types = 

    @staticmethod
    def processor(ext):
        return MusicFile.known_types[ext]()

def file_types(*exts):
    def registered_class(cls):
        for ext in exts: MusicFile.known_types[ext] = cls
        return cls
    return registered_class

@file_types('mp3')
class Mp3(MusicFile):
    def greet(self):
        print 'Hi .mp3!'

@file_types('mid', 'midi')
class Midi(MusicFile):
    def greet(self):
        print 'Hi, Music Instruments Digital Interface!'

pcsor = MusicFile.processor('mp3')
pcsor.greet()                      # Hi .mp3!
pcsor = MusicFile.processor('mid')
pcsor.greet()                      # Hi, Music Instruments Digital Interface!
pcsor = MusicFile.processor('midi')
pcsor.greet()                      # Hi, Music Instruments Digital Interface!
pcsor = MusicFile.processor('s3m') # KeyError: 's3m'
pcsor.greet()

【讨论】:

确实,我使用了工厂,所以创建了正确的对象,但也许每次添加新的子类型时,它看起来的字典都可以由元类构建?我想知道元类的一个好的用途是否是创建一个约束,以限制类必须如何看待(例如,它的方法)才能使其发挥作用

从 Python 中的元类继承

】从Python中的元类继承【英文标题】:InheritancefrommetaclassesinPython【发布时间】:2022-01-1807:49:01【问题描述】:我有一个简单的元类,它将以“get_”开头的类的方法转换为属性:classPropertyConvertMetaclass(type):def__new__(mcs,future_class_nam... 查看详情

python中的元类作用?

...,并且是它自己的类型。你将无法type纯粹使用Python重新创建类似的东西,但是Python有点作弊。要在Python中创建自己的元类,你实际上只想将其子类化type。元类最常用作类工厂。class执行该语句时,Python首先将class语句的主体作为... 查看详情

实现特殊的元类。继承类中的非化字段

】实现特殊的元类。继承类中的非化字段【英文标题】:Implementspecialmetaclass.Nonifyfieldininheritedclass【发布时间】:2017-10-2722:18:36【问题描述】:我有一个任务:实现元类“ModelCreator”,允许声明类以下形式的字段:classStudent(object... 查看详情

python元类继承问题

...】:我有一个有点奇怪的元类问题。我正在使用元类动态创建一个继承自另一个超类的“兄弟”类,并将其分配为原始类的属性。下面是一个最小的设置:classMeta(type):def__new__(cls,name,parents,dct):sdct=dct.copy()dct[\'s 查看详情

为啥类定义的元类关键字参数接受可调用的?

】为啥类定义的元类关键字参数接受可调用的?【英文标题】:Whydoestheclassdefinition\'smetaclasskeywordargumentacceptacallable?为什么类定义的元类关键字参数接受可调用的?【发布时间】:2017-02-2302:20:24【问题描述】:背景Python3documentatio... 查看详情

将元类与多重继承结合使用的 TypeErrors

】将元类与多重继承结合使用的TypeErrors【英文标题】:TypeErrorsusingmetaclassesinconjunctionwithmultipleinheritance【发布时间】:2011-01-1307:42:18【问题描述】:我有两个关于元类和多重继承的问题。第一个是:为什么我会得到类Derived的TypeE... 查看详情

python中的元编程(代码片段)

...概念是元类。什么是元类呢,具体到Python,用来创建类的类,就叫元类。元类是制造类的工厂。在Python中,一个普通类创建出来的东西是类的实例,实例是一个对象。而元类也是一种类,它创建出来的东西... 查看详情

TypeError:元类冲突:派生类的元类必须是其所有基类的元类的(非严格)子类

...【发布时间】:2017-10-0418:42:37【问题描述】:尝试使用类创建GUI,但我一直遇到此错误的问题。我不确定这 查看详情

为啥我的元类实现失败并出现关于无法创建 NoneType 实例的 TypeError

】为啥我的元类实现失败并出现关于无法创建NoneType实例的TypeError【英文标题】:WhydoesmymetaclassimplementationfailwithaTypeErroraboutnotbeingabletocreateNoneTypeinstances为什么我的元类实现失败并出现关于无法创建NoneType实例的TypeError【发布时间... 查看详情

使用 Boost.Python 设置包装类的元类

】使用Boost.Python设置包装类的元类【英文标题】:SettingmetaclassofwrappedclasswithBoost.Python【发布时间】:2012-02-2016:40:20【问题描述】:我有一个用C++定义的Event类,我使用Boost向Python公开。我的脚本应该从这个类派生,我想在定义新... 查看详情

子类 Django ModelBase(Django 模型的元类)

...许多类中被重用。所以我想从一个Owned类继承,让我存储创建该类的用户。我还没有尝试填充该字段,我只是需要它存 查看详情

使用装饰器设置类的元类

】使用装饰器设置类的元类【英文标题】:Settingaclass\'metaclassusingadecorator【发布时间】:2012-06-2022:33:34【问题描述】:在thisanswer之后,似乎可以在使用以下*定义类之后更改类的元类:classMyMetaClass(type):#Metaclassmagic...classA(object):pa... 查看详情

面向对象,元类,控制类,对象的创建

...行函数类自定义元类的目的?1.可以通过call来控制对象的创建过程?2.可用控制类的创建过程"""自定义一个元类元类也是一个类但是需要继承typeclassMyMeta(type):?self表示要创建对象的那个类(Person)*args是调用Person类时传入的参数?? de... 查看详情

元类,异常处理

...用自定义的类---->自定义的对象自定义类:#class关键字创建自定义类的底层的工作原理,分为四步例如:classOldboyTeacher(object,):#1.先拿到类名:‘OldboyTeacher‘#2.再拿到类的基类们:( 查看详情

如何确定一个类的元类?

...ype(cls)@JimIMO一个好的答案可以解释为什么类对象的类型是创建它的元类。如果OP的问题以实际要求why而 查看详情

为啥元类不能访问由元类定义的类的子类继承的属性?

】为啥元类不能访问由元类定义的类的子类继承的属性?【英文标题】:Whydoesametaclassnothaveaccesstotheattributesinhereitedfromasubclassofaclassdefinedbythemetaclass?为什么元类不能访问由元类定义的类的子类继承的属性?【发布时间】:2015-07-06... 查看详情

TypeError:python中的元类冲突

...705:56:43【问题描述】:我正在使用django-tastypie为我的webapp创建一个restAPI。我想创建如下所述的类而不明确输入它们(我有超过100个类)classCityResource(ModelResource):classMeta:queryset=C 查看详情

具有自定义元类行为的 Python 元类

...:06:26【问题描述】:我正在使用Python2.7中的元类。所以我创建了一个如下所示的代码:classM(type):def__new__(meta,name,parents,attrs):print\'Inmetanew\'returnsuper(meta,m 查看详情