以下是我的第一个问题的链接:Creating class instance from dictionary?所以我试图从字典创建类实例,其中包含类没有的键。例如:
class MyClass(object):
def __init__(self, value1, value2):
self.attr1 = value1
self.attr2 = value2
dict = {'attr1': 'value1', 'attr2': 'value2', 'redundant_key': 'value3'}
在创建类实例之前,我必须从dict
中删除此redundant_key
dict.pop('redundant_key', None)
new_instance = MyClass(**dict)
问题是我有几个类和几个带有很多键的dicts(我有几个json格式的响应,表示为dicts,我想从这个json响应中创建对象)。我已经找到了上一个问题的临时解决方案 - 如何删除冗余密钥。我只能用我需要的键从旧dict创建新的dict:
new_dict = {key: old_dict[key] for key in allowed_keys}
所以这是代码:
class MyClass(object):
def __init__(self, value1, value2):
self.attr1 = value1
self.attr2 = value2
dict = {'attr1': 'value1', 'attr2': 'value2', 'redundant_key': 'value3'}
new_instance = MyClass(**{key: dict[key] for key in allowed_keys})
我现在需要的是获得allowed_keys
。所以问题 - 有没有办法在不创建类实例的情况下获取类实例属性?
答案 0 :(得分:2)
如果您坚持使用过于通用的字典来初始化对象,只需定义__init__
接受,但忽略额外的键。
class MyClass(object):
def __init__(self, attr1, attr2, **kwargs):
self.attr1 = attr1
self.attr2 = attr2
d = {'attr1': 'value1', 'attr2': 'value2', 'extra_key': 'value3'}
new_instance = MyClass(**d)
如果你不能修改__init__
(如果它继承自SQLAlchemy声明性基础就是这种情况),添加一个替代构造函数来接受所有关键字参数,但选择你需要的那些。 / p>
class MyClass(Base):
@classmethod
def from_dict(cls, **kwargs):
# Let any KeyErrors propagate back to the caller.
# They're the one who forgot to make sure **kwargs
# contained the right keys.
value1 = kwargs['attr1']
value2 = kwargs['attr2']
return cls(value1, value2)
new_instance = MyClass.from_dict(**d)
答案 1 :(得分:1)
免责声明:这解决了OP所询问的问题(获取实例的属性),而不是他们需要的内容。这似乎是构造函数的参数列表。
你无法做你想做的事。在python中,属性被动态地添加到类的实例中。同一个类的两个实例可以具有不同的属性。嗯......确切地说,有一些叫做实例属性和类属性的东西。
实例属性是与类实例关联的属性。类属性与其定义相关联,即如果您写了(MyClass.foo
)
如果查看示例,则会在__init__
self
上添加属性,因此它们是实例属性。
你可以做的是创建一个有效的实例并检查它(查看下面的示例),提供allowed_keys
的静态列表(例如作为类属性),或者某种方式需要allowed_keys
作为构造函数参数。所有这些都是一种解决方法,因为你真正需要的是不可能的。他们有利有弊。
例如:
class MyClass(object):
def __init__(self, value1, value2):
self.attr1 = value1
self.attr2 = value2
instance = MyClass(1,2) # create a valid object
instance_attributes = instance.__dict__.keys() # inspect it
print(instance_attributes)
答案 2 :(得分:1)
以下是如何执行您要执行的操作:使用适当的参数实例化您的类。请注意,您没有检查__init__
创建的属性,而是它接受的参数。它对它们的作用并不重要 - 当您遇到它时,这不是您的关注调用构造函数。
myparams = {'attr1': 'value1', 'attr2': 'value2', 'redundant_key': 'value3'}
usable = { k:v for k, v in myparams if k in MyClass.__init__.__code__.co_varnames }
new_instance = MyClass(**usable)
为了清晰起见,我使用了过滤字典理解,但是当然可以在一步中完成。
PS。请注意,如果您的某个词典恰好包含密钥self
,则会出现问题。 :-)如果您不信任您的数据源,可能需要将其过滤掉。
答案 3 :(得分:1)
您应该已经提到过,您需要SQLAlchemy-Mapper-Class的列。这是一项更容易的任务:
dict = {'attr1': 'value1', 'attr2': 'value2', 'redundant_key': 'value3'}
columns = YourTable.__table__.columns.keys()
entry = YourTable(**{k: dict[k] for k in columns})