有没有办法在不创建类实例的情况下获取类实例属性?

时间:2015-05-08 16:47:25

标签: python dictionary class-instance-variables

以下是我的第一个问题的链接: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。所以问题 - 有没有办法在不创建类实例的情况下获取类实例属性?

4 个答案:

答案 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})