2

これが私の最初の質問へのリンクです:辞書からクラスインスタンスを作成していますか?
そのため、クラスにないキーを保持する辞書からクラス インスタンスを作成しようとしています。例えば:

class MyClass(object):
    def __init__(self, value1, value2):
        self.attr1 = value1
        self.attr2 = value2

dict = {'attr1': 'value1', 'attr2': 'value2', 'redundant_key': 'value3'}

クラスインスタンスを作成する前に、これredundant_keyをdictから削除する必要があります

dict.pop('redundant_key', None)
new_instance = MyClass(**dict)

問題は、いくつかのクラスと多くのキーを持ついくつかのディクテーションがあることです (ディクテーションとして表される json 形式の応答がいくつかあり、この json 応答からオブジェクトを作成したい)。前の質問から暫定的な解決策をすでに見つけました-冗長キーを削除する方法。必要なキーのみを使用して、古い辞書から新しい辞書を作成できます。

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

4 に答える 4

3

オブジェクトを初期化するために過度に一般的な辞書を使用することを主張する場合は__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 宣言ベースから継承する場合のようです)、代替コンストラクターを追加して、すべてのキーワード引数を受け入れますが、必要なものを選択します。

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)
于 2015-05-08T17:27:37.267 に答える
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)

わかりやすくするためにフィルター処理された辞書内包表記を使用しましたが、もちろん 1 つのステップで行うこともできます。

PS。辞書の 1 つに key が含まれていると問題が発生することに注意してくださいself。:-) データ ソースが信頼できない場合は、除外することをお勧めします。

于 2015-05-08T17:18:34.063 に答える
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})
于 2015-05-08T17:43:04.823 に答える
1

免責事項:これは、OPが求めていたもの(インスタンスの属性の取得)に答えますが、必要なものではありません。コンストラクターのパラメーターリストのようです。

やりたいことはできません。Python では、属性はクラスのインスタンスに動的に追加されます。同じクラスの 2 つのインスタンスが異なる属性を持つことができます。うーん…正確には、インスタンス属性、クラス属性というものがあります。

インスタンス属性は、クラスのインスタンスに関連付けられたものです。クラス属性はその定義に関連付けられています。つまり、( MyClass.foo)

例を見ると、属性は__init__on中に追加されているselfため、インスタンス属性です。

あなたができることは、有効なインスタンスを作成してそれを検査する(以下のを見てください)、静的リストを提供するallowed_keys(例えば、クラス属性として)、または何らかの方法allowed_keysでコンストラクタパラメータとしてrequireすることです。本当に必要なものは不可能であるため、これらはすべて一種の回避策です。それらには長所と短所があります。

:

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)
于 2015-05-08T17:01:18.210 に答える