根据对象现有的属性或属性,以更Python的方式改进重复循环

时间:2019-02-20 17:21:16

标签: python

我有一个具有多个属性的Object(从数据库中检索):

db_obj.default_attr= "textdefault"
 db_obj.additional = {
    "alpha": "texta",
    "beta": "textb",   
    "gama": "textg",
    "teta": "textt",
     ...
}
 db_obj.name: "some_name"
 .... 

additional属性也是一个对象,可以为空/空/不具有所有值,在db中为null或json

然后types是一个数组:["alpha", "gama", ...]


我具有以下功能,即:

set_att(obj=db_object, types=types)

我需要基于types数组创建一个新对象:

属性示例:

  new_obj.alpha = "texta"
  new_obj.gama =  "textdefault"  # because gama was not found in additional

我定义了函数:

def set_att(db_obj=None, types=None):

 new_obj = types.SimpleNamespace()

try:

  add = db_obj.getattr(additional)

  # cycle thru types, and assign the value from the db_obj if exist or the     default_attr value
  for item_type in types: 
     try:
        setattr(new_obj, item_type, add.getattr(item_type))
      except AttributeError: 
         setattr(new_obj, item_type, obj.getattr(default_attr))   

 # if there is not addtional I still set default for type
except AttributeError:
    for item_type in types: 
         setattr(new_obj, item_type, obj.getattr(default_attr)

它看起来很幼稚,我正在寻找一个更Python化的选项。

2 个答案:

答案 0 :(得分:2)

您可以使用hasattr来检查对象是否具有属性,而不是捕获AttributeException。这将使代码更易于阅读,因为它显式地处理了不存在该属性的预期情况。使用异常会使它看起来好像是一个错误情况。

 for item_type in types:
     if hasattr(add, item_type):
         value = getattr(add, item_type) 
     else:
         value = getattr(obj, default_attr)
     setattr(new_obj, item_type, value)  

答案 1 :(得分:1)

您可以创建一个此类来访问数组键作为对象属性

class CustomDict(dict):

    def __getattr__(self, key):
        return self[key]

    def __getitem__(self, key):
        try:
            return super(CustomDict, self).__getitem__(key)
        except KeyError:
            return None

    def get(self, key, default=None):
        try:
            return super(CustomDict, self).__getitem__(key)
        except KeyError:
            return self.build(default)

    @classmethod
    def build(cls, orig):
        if isinstance(orig, basestring):
            return orig
        if isinstance(orig, Sequence):
            return [cls.build(item) for item in orig]
        elif isinstance(orig, Mapping):
            new = cls()
            for key, value in orig.iteritems():
                new[key] = cls.build(value)
            return new
        return orig

像这样使用::

additional = {
    "alpha": "texta",
    "beta": "textb",   
    "gama": "textg",
    "teta": "textt",
}
new=CustomDict(additional)

然后您可以访问以下属性:

print(new.alpha) # print texta
print(new.xyz)   # print None