如何在Python中将参数传递给__metaclass__

时间:2017-12-14 14:22:39

标签: python inheritance arguments metaclass

我有一个行数据的元类。任何记录都应该属于这个类,所以你可以看到下面我试图固有两次,一次是程序,一次是资产。但是我需要将一个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 diction ......所以我觉得应该有办法做到这一点而不重复这个每个班级......班级无所不在的全部要点:

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)

1 个答案:

答案 0 :(得分:2)

你需要的只是普通的类继承,也许是一个普通的函数,可以作为你的类的工厂。

因为你唯一需要的是键的有序列表,它存在于类的插槽中,就是它 - 你可以用你已经拥有的代码构建一个基类,并且只需继承它你的班级结构。

如果你想要一个映射的全部功能,比如dict,能够检索元素,获取长度等等,我建议继承collections.abc.MutableMapping而不是OrderedDict。即使因为,如果你继承OrderedDict形式,__slots__声明将毫无价值 - dicts和OrderedDict保持他们的数据以不能通过Python代码访问的方式排列 - 你可以将你的代码保存在每个类中{{1} }。

此外,__slots__的制作方式要求您实现一组最小的方法,从中衍生出dict的所有功能。

所以,调整你的上一个示例类,你会有类似的东西。

collections.abc.MutableMapping

这就是它的工作:

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