Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中,如何将参数传递给_元类__Python_Inheritance_Arguments_Metaclass - Fatal编程技术网

在Python中,如何将参数传递给_元类_

在Python中,如何将参数传递给_元类_,python,inheritance,arguments,metaclass,Python,Inheritance,Arguments,Metaclass,我有一个用于行数据的元类。任何记录都应该是这个类固有的,所以你们可以看到下面我尝试固有两次,一次用于程序,一次用于资产。但是我需要将OrderedDict传递给元类,或者交替地将slot和init函数移动到实际的类中。。。但这似乎是在浪费空间 ############################################################### #NORMALIZED CLASS ROWS ########################################

我有一个用于行数据的元类。任何记录都应该是这个类固有的,所以你们可以看到下面我尝试固有两次,一次用于程序,一次用于资产。但是我需要将OrderedDict传递给元类,或者交替地将slot和init函数移动到实际的类中。。。但这似乎是在浪费空间

###############################################################
#NORMALIZED CLASS ROWS 
###############################################################
class MetaNormRow(type, OrderedDict):
    __slots__ = list(OrderedDict.keys())

    def __init__(self, **kwargs):
        for arg, default in OrderedDict.items():
            setattr(self, arg, re.sub(r'[^\x00-\x7F]', '', kwargs.get(arg, default)))
            print (str(arg) + " : "+ str(re.sub(r'[^\x00-\x7F]', '', kwargs.get(arg, default))))

    def items(self):
        for slot in self.__slots__:
            yield slot, getattr(self, slot)

    def values(self):
        for slot in self.__slots__:
            yield getattr(self, slot)

class NormAsset(object):
    __metaclass__ = MetaNormRow(DefaultAsset)

class NormProg(object):
    __metaclass__ = MetaNormRow(DefaultProgs)
下面是我将如何使用NormAsset和Prog类:

kwargs = {
    "status": norm_status,
    "computer_name": norm_comp_name,
    "domain_name": norm_domain,
    "serial_num": norm_serial,
    "device_type": norm_device_type,
    "mfr": norm_mfr,
    "model": norm_model,
    "os_type": norm_os_type,
    "os_ver": norm_os_ver,
    "os_subver": norm_os_subver,
    "location_code": norm_location_code,
    "tan_id": tan_id,
    "tan_comp_name": tan_comp_name,
    "tan_os": tan_os,
    "tan_os_build": tan_os_build,
    "tan_os_sp": tan_os_sp,
    "tan_country_code": tan_country_code,
    "tan_mfr": tan_mfr,
    "tan_model": tan_model,
    "tan_serial": tan_serial
}
norm_tan_dict[norm_comp_name] = rows.NormAsset(**kwargs)
为了澄清,以下功能100%工作。。。但我需要10个,唯一不同的是DefaultAsset的措辞。。。所以我觉得应该有一种方法来做到这一点,而不是在每节课上重复这一点。。。阶级本质的全部要点:

class NormAsset(object):
    __slots__ = list(DefaultAsset.keys())

    def __init__(self, **kwargs):
        for arg, default in DefaultAsset.items():
            setattr(self, arg, re.sub(r'[^\x00-\x7F]', '', kwargs.get(arg, default)))
            #print (str(arg) + " : "+ str(re.sub(r'[^\x00-\x7F]', '', kwargs.get(arg, default))))

    def items(self):
        for slot in self.__slots__:
            yield slot, getattr(self, slot)

    def values(self):
        for slot in self.__slots__:
            yield getattr(self, slot)

您需要的只是普通的类继承,也许是一个普通的函数来作为类的工厂

因为您只需要在类的插槽中出现的键的有序列表,就是这样-您可以用您已有的代码构建一个基类,并简单地从中继承类结构

如果您想要映射的全部功能,比如dict,能够检索元素、获取长度等等,我建议从
collections.abc.MutableMapping
继承,而不是从OrderedDict继承。即使是因为,如果您继承form OrderedDict,那么
\uuuuu slots\uuuu
声明将毫无价值-dicts和OrderedDict以Python代码无法访问的方式排列其数据-您可以在每个类
\uuuu slots\uuu
中单独保留代码

另外,
collections.abc.MutableMapping
的编制方式要求您实现一组最小的方法,从中可以从dict派生所有功能

因此,通过修改上一个示例类,您将得到如下内容

from collections.abc import MutableMapping

class BaseAsset(MutableMapping):
    # Base class for slotted classes need to have __slots__.
    __slots__ = []
    default_asset = None

    def __init__(self, **kwargs):
        for arg, default in self.__class__.default_asset.items():
            value = kwargs.get(arg, default)
            setattr(self, arg, re.sub(r'[^\x00-\x7F]', '', value))

    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        if item in self.__slots__:
            return setattr(self, item, value)
        raise KeyError

    def __delitem__(self, item):
        if item in self.__slots__:
            return delattr(self, item)
        raise KeyError

    def __iter__(self):
        yield from iter(self.__slots__)

    def __len__(self):
        return len(self.__slots__)

    def __repr__(self):
        return f"{self.__class__.__name__}(**{dict(self)})"



def asset_class_factory(name, DefaultAsset):

    class CustomAsset(BaseAsset):
        __slots__ = list(DefaultAsset.keys())
        default_asset = DefaultAsset

    CustomAsset.__name__ = name
    return CustomAsset
这就是它的工作原理:

In [182]: d = {"banana": "nanica"} 

In [183]: FruitClass = asset_class_factory("FruitClass", d)

In [184]: f = FruitClass()

In [185]: f.banana
Out[185]: 'nanica'

In [186]: f
Out[186]: FruitClass(**{'banana': 'nanica'}

. 我想我从未在元类中见过dunder init,但我肯定没有经验。你在哪里遇到过这样的结构?不确定。。。我多年来没有做过这种深层次的继承,它是C++的。底线是。。。行对象,如recordclass对象,应该是标准的。。。这意味着我不必在行的每次迭代中重复该行概念的任何通用代码,因为行数据已更改。afaik元类实际上不是关于继承或子类化的。元类可用于控制生成类。你应该搜索python元类的视频并观看一些——pyvideo.org上的Pycon视频通常都很不错。还有,为什么讨厌“非ASCII文本”?其他字符是确定性的,只需使用显式编码,您就可以让您的程序处理来自真实世界的数据(使用诸如“resumé”之类的外来词)。我建议读下面的文章。请不要被它的标题冒犯或害怕这看起来不像是元类的用例。。。