メソッド set.union

メソッド set.union のヘルプ情報を確認します。
>>> help(set.union)
Help on method_descriptor:

union(...)
Return the union of two sets as a new set.

(i.e. all elements that are in either set.)

これを見て、2つの集合をもとに、新たな集合(和集合)が得られるのが分かります。実際に、その動作を確認してみましょう。
>>> s1 = set("AB")
>>> s2 = set("BC")
>>> s1.union(s2)
set(['A', 'C', 'B'])

2つの集合 s1/s2 の「どちらかに」含まれる要素を列挙した、集合が得られます。

メソッド set.difference

メソッド set.difference のヘルプ情報を確認します。
>>> help(set.difference)
Help on method_descriptor:

difference(...)
Return the difference of two sets as a new set.

(i.e. all elements that are in this set but not the other.)

これを見て、2つの集合をもとに、新たな集合(差集合)が得られるのが分かります。実際に、その動作を確認してみましょう。
>>> s1 = set("AB")
>>> s2 = set("BC")
>>> s1.difference(s2)
set(['A'])

集合 s1 から集合 s2 の要素を除くと、要素 'A' だけが残ります。
>>> s2.difference(s1)
set(['C'])

集合 s2 から集合 s1 の要素を除くと、要素 'C' だけが残ります。

ソースコード:SetCollection.Union(object)

(メソッド set.union に相当する)メソッド Union の定義を含む、ソースコードの断片を次に示します。他のメソッド intersection/difference/symmetric_difference についても、同様です。
# IronPython-1.1.2/Src/IronPython/Runtime/Set.cs
public class SetCollection : ISet ...

#region NonOperator Operations
[PythonName("union")]
public object Union(object s) {
return SetHelpers.Union(this, s);
}

[PythonName("intersection")]
public object Intersection(object s) {
return SetHelpers.Intersection(this, s);
}

[PythonName("difference")]
public object Difference(object s) {
return SetHelpers.Difference(this, s);
}

[PythonName("symmetric_difference")]
public object SymmetricDifference(object s) {
return SetHelpers.SymmetricDifference(this, s);
}

public class FrozenSetCollection : ISet ...
#region NonOperator Operations
...

メソッド Union では、メソッド SetHelpers.Union の実引数に、this を指定しています。これは、静的クラス SetHelpers で共有する操作を実現しているので、それに自身 this の処理を委ねるためです。このとき(SetCollection のインスタンス)this は、インターフェース ISet の規定に従うものとします。他方のクラス FrozenSetCollection についても、同様です。

クラス:SetHelpers

次に示す静的メソッド本体に共通する、次のような構造が見えてきます。
ISet set = SetHelpers.MakeSet(x, x);
...
set.PrivFreeze();
return set;

インターフェース ISet の規定に従う、インスタンス set を生成して、これをリターン値します。このとき、可能なら変更不能な set が得られるようにします。

ソースコード:ISet.PrivFreeze()

メソッド ISet.PrivFreeze の定義を含む、ソースコードの断片を次に示します。
internal interface ISet : IEnumerable {
void PrivFreeze();

インターフェース ISet を実現するクラス(SetCollection/FrozenSetCollection)では、メソッド PrivFreeze を実現する必要があります。
public class SetCollection : ISet ...
void ISet.PrivFreeze() {
// nop for non-frozen sets.
}

クラス SetCollection では、なにもする必要がないので、メソッドの本体は空です。
public class FrozenSetCollection : ISet ...
int hashCode;

void ISet.PrivFreeze() {
CalculateHashCode();
}
void CalculateHashCode() {
hashCode = 6551;
...
}

クラス FrozenSetCollection では、ハッシュコードを再計算する必要があります。(補助関数として)メソッド CalculateHashCode では、インスタンス属性 hashCode の値を再設定します。その詳細は、ここでは割愛します。


# IronPython-1.1.2/Src/IronPython/Runtime/Set.cs
static class SetHelpers {
...
public static ISet Union(ISet x, object y) {
ISet set = SetHelpers.MakeSet(x, x);
IEnumerator ie = Ops.GetEnumerator(y);
while (ie.MoveNext()) {
set.PrivAdd(ie.Current);
}
set.PrivFreeze();
return set;
}

public static ISet Intersection(ISet x, object y) {
ISet res = SetHelpers.MakeSet(x);
IEnumerator ie = Ops.GetEnumerator(y);
while (ie.MoveNext()) {
if (x.Contains(ie.Current) == Ops.TRUE)
res.PrivAdd(ie.Current);
}
res.PrivFreeze();
return res;
}

public static ISet Difference(ISet x, object y) {
ISet res = SetHelpers.MakeSet(x, x) as ISet;
Debug.Assert(res != null);

IEnumerator ie = Ops.GetEnumerator(y);
while (ie.MoveNext()) {
if (res.Contains(ie.Current) == Ops.TRUE) {
res.PrivRemove(ie.Current);
}
}
res.PrivFreeze();
return res;
}

public static ISet SymmetricDifference(ISet x, object y) {
SetCollection otherSet = new SetCollection(Ops.GetEnumerator(y)); //make a set to deal w/ dups in the enumerator
ISet res = SetHelpers.MakeSet(x, x) as ISet;
Debug.Assert(res != null);

foreach (object o in otherSet) {
if (res.Contains(o) == Ops.TRUE) {
res.PrivRemove(o);
} else {
res.PrivAdd(o);
}
}
res.PrivFreeze();
return res;
}

  • -

メソッド set.intersection

メソッド set.intersection のヘルプ情報を確認します。
>>> help(set.intersection)
Help on method_descriptor:

intersection(...)
Return the intersection of two sets as a new set.

(i.e. all elements that are in both sets.)

これを見て、2つの集合をもとに、新たな集合(積集合)が得られるのが分かります。実際に、その動作を確認してみましょう。
>>> s1 = set("AB")
>>> s2 = set("BC")
>>> s1.intersection(s2)
set(['B'])

2つの集合 s1/s2 の「どちらにも」含まれる要素を列挙した、集合が得られます。

メソッド set.symmetric_difference

メソッド set.symmetric_difference のヘルプ情報を確認します。
>>> help(set.symmetric_difference)
Help on method_descriptor:

symmetric_difference(...)
Return the symmetric difference of two sets as a new set.

(i.e. all elements that are in exactly one of the sets.)

これを見て、2つの集合をもとに、新たな集合(対称差集合)が得られるのが分かります。実際に、その動作を確認してみましょう。
>>> s1 = set("AB")
>>> s2 = set("BC")
>>> s1.symmetric_difference(s2)
set(['A', 'C'])

2つの集合 s1/s2 の「どちらか一方にだけ」含まれる要素を列挙した、集合が得られます。

ソースコード:SetHelpers.MakeSet(object, ISet)

静的メソッド MakeSet の定義を含む、ソースコードの断片を次に示します。
public static ISet MakeSet(object setObj, ISet set) {
Type t = setObj.GetType();
if (t == typeof(SetCollection)) {
return new SetCollection(set);
} else if (t == typeof(FrozenSetCollection)) {
return new FrozenSetCollection(set);
} else {
// subclass
UserType ut = Ops.GetDynamicType(setObj) as UserType;
Debug.Assert(ut != null);
ISet res = Ops.Call(ut) as ISet;

Debug.Assert(res != null);
res.SetData(set);
return res;
}
}

与えられた引数 setObj の型に合わせて、引数 set と同じ要素を列挙したインスタンス(SetCollection/FrozenSetCollection)を生成して、それをリターン値とします。メソッド本体を見ると、次に示す典型的な C# のイディオムが記述してあります。
Type t = obj.GetType();
if (t == typeof(A)) {
return new A(...);
} else if (t == typeof(B)) {
return new B(...);
} else {
... // 利用者が定義した型
}

与えられた obj の型に合わせて、適切なインスタンスを生成します。
《参照》メソッド @GetType の詳細は、http://msdn.microsoft.com/en-us/library/system.collections.ienumerator_members.aspx http://msdn.microsoft.com/en-us/library/system.collections.ienumerator_members.aspxを参照してください。□