ソースコード:DictOps.Update(IDictionary<>, object)

内部クラス DictOps では、クラス Dict で規定するメソッドに対する、実質的な処理群(Ops)を実現します。これらのメソッドを static 宣言することで「関数」として再定義します。また、メソッド呼び出しの対象となるインスタンス(実引数 this)が、ここでの仮引数 self になります。

    internal static class DictOps {
public static void Update(IDictionary self, object b) {
object keysFunc;
IDictionary dict = b as IDictionary;
if (dict != null) {
IDictionaryEnumerator e = dict.GetEnumerator();
while (e.MoveNext()) {
self[DictOps.NullToObj(e.Key)] = e.Value;
}
} else if (Ops.TryGetAttr(b, SymbolTable.Keys, out keysFunc)) {
// user defined dictionary
IEnumerator i = Ops.GetEnumerator(Ops.Call(keysFunc));
while (i.MoveNext()) {
self[DictOps.NullToObj(i.Current)] = Ops.GetIndex(b, i.Current);
}
} else {
// list of lists (key/value pairs), list of tuples,
// tuple of tuples, etc...
IEnumerator i = Ops.GetEnumerator(b);
int index = 0;
while (i.MoveNext()) {
if (!AddKeyValue(self, i.Current)) {
throw Ops.ValueError("dictionary update sequence element #{0} has bad length; 2 is required", index);
}
index++;
}
}
}

静的メソッド Update では、引数 b が、インターフェース IDictionary の規定に従うかどうかで、後の処理を振り分けます。すると、次のような構造が見えてきます。

    IDictionary dict = b as IDictionary;
if (dict != null) { // IDictionary の規定に従う
...
} else if (...) {
// user defined dictionary
...
} else {
// list of lists (key/value pairs), list of tuples,
// tuple of tuples, etc...
...
}

if に続く条件式 dict != null が成立するなら、インターフェース IDictionary で規定したプロトコルに従って、dict を処理します。それ以外は、工夫が必要です。2番目の if ブロックについては、別の記事「利用者定義の辞書を扱う」で解説するので、ここでは割愛します。


Previous〈2/3〉Next

ソースコード:Dict.Update(...)

(メソッド dict.update に相当する)メソッド Update の定義を含む、ソースコードの断片を次に示します。

# IronPython-1.1.2/Src/IronPython/Runtime/Dict.cs
[PythonType("dict")]
public class Dict : ... IDictionary ... {
...
#region Python dict implementation
[PythonName("update")]
public void Update() {
}

[PythonName("update")]
public void Update([ParamDict] Dict dict) {
DictOps.Update(this, dict);
}

[PythonName("update")]
public void Update(object b) {
DictOps.Update(this, b);
}

[PythonName("update")]
public void Update(object b, [ParamDict] Dict dict) {
DictOps.Update(this, b);
DictOps.Update(this, dict);
}

前述したヘルプ情報から、1番目の Update() は、引数を省略した D.update() に相当します。また、2番目の Update(Dict) は、キーワド引数を指定した D.update(**F) に相当します。そして、3番目の Update(object) は、任意の引数を指定した D.update(E) に相当します。最後の Update(object,Dict) が、これら3つのメソッド Update を包括します。
メソッド Update(object,Dict) では、メソッド DictOps.Update の実引数に、this を指定しています。これは、内部クラス DictOps ですべての操作を実現しているので、それに自身 this の処理を委ねるためです。このとき(Dict のインスタンス)this は、インターフェース IDictionary の規定に従うものとします。

《参照》インターフェース IDictionary:詳細は、http://msdn.microsoft.com/en-us/library/system.collections.idictionary.aspx を参照してください。