如何在 Python 中将参数传递给 __metaclass__
How do you pass arguments to __metaclass__ in Python
我有一个用于行数据的元数据class。任何记录都应该从这个 class 继承,所以你可以在下面看到我试图继承两次,一次用于程序,一次用于资产。但是我需要将 OrderedDict 传递给 metaclass 或者将插槽和初始化函数移动到实际的 classes...但这似乎是对 space.[= 的浪费15=]
###############################################################
#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 classes:
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... class 继承的全部要点:
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)
你需要的只是普通的 class 继承,也许还有一个普通的函数作为你的 classes 的工厂。
由于您唯一需要的是键的有序列表,它出现在 classes 的插槽中,仅此而已 - 您可以构建一个基础 class您已经拥有的代码,并简单地从它继承您的 class 结构。
如果您想要映射的全部功能,例如 dict,能够检索元素、获取长度等,我建议您继承 collections.abc.MutableMapping
而不是 OrderedDict。即使是因为,如果您继承 OrderedDict,__slots__
声明将毫无价值 - 字典和 OrderedDict 以无法通过 Python 代码访问的方式排列它们的数据 - 您可以将代码单独保存在每个 class __slots__
.
此外,collections.abc.MutableMapping
的制作方式要求您实现最少的方法集,从中派生出字典的所有功能。
所以,改编你的最后一个例子 class,你会得到这样的东西。
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'}
我有一个用于行数据的元数据class。任何记录都应该从这个 class 继承,所以你可以在下面看到我试图继承两次,一次用于程序,一次用于资产。但是我需要将 OrderedDict 传递给 metaclass 或者将插槽和初始化函数移动到实际的 classes...但这似乎是对 space.[= 的浪费15=]
###############################################################
#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 classes:
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... class 继承的全部要点:
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)
你需要的只是普通的 class 继承,也许还有一个普通的函数作为你的 classes 的工厂。
由于您唯一需要的是键的有序列表,它出现在 classes 的插槽中,仅此而已 - 您可以构建一个基础 class您已经拥有的代码,并简单地从它继承您的 class 结构。
如果您想要映射的全部功能,例如 dict,能够检索元素、获取长度等,我建议您继承 collections.abc.MutableMapping
而不是 OrderedDict。即使是因为,如果您继承 OrderedDict,__slots__
声明将毫无价值 - 字典和 OrderedDict 以无法通过 Python 代码访问的方式排列它们的数据 - 您可以将代码单独保存在每个 class __slots__
.
此外,collections.abc.MutableMapping
的制作方式要求您实现最少的方法集,从中派生出字典的所有功能。
所以,改编你的最后一个例子 class,你会得到这样的东西。
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'}