3

私はちょっとここで立ち往生しています。私は基本的に実験段階にあり、算術演算の場合に 1 として機能する「不明な」値を割り当てることができることを除いて、それがあなたintの古き良きものとまったく同じように機能するようにサブクラス化できるかどうか疑問に思いますint.

私が言うことができるように:

>>> uint(5) + 5
10
>>> uint('unknown')
unknown
>>> int(uint('unknown'))
1
>>> uint('unknown') + 5
6
>>>

実際、float('inf')必要なのは整数と単一の「特別な」値だけであることを除けば、すでに で動作しているものと何らかの形で似ています。

私が想像していたのは、次のようなものです。

class uint(int):

    def __init__(self, value):
        self.value = value
        self.unknown = self.value == "unknown"

    def __int__(self):
        return 1 if self.unknown else self.value

    def __str__(self):
        return "unknown" if self.unknown else str(self.value)

ValueError: invalid literal for int() with base 10: 'unknown'しかし、この例は、インスタンス化しようとするとスローされuint('unknown')ます。

それで、これは可能ですか?どうすればそれについて行くでしょうか?


背景レベル 1

誰かが尋ねた場合に備えて、背景は、イテラブルのリストがあり、を使用して新しいリストを作成したいということですitertools.product__len__しかし、前に、一部のイテレーターがそれを実装する場合に備えて、最終要素の (最小) 数を推測できるようにするために を利用したいと考えています。したがって、最終的な数値に関しては、 を持たない iterable については__len__、1 と想定しています。

私がこれをやりたい理由class uint(int)は、個別のカウントを安全に公開できるようにしたいからです (誰かが "loading (1500 = 10 * 10 * unknown * 15) elements" のようなログをプッシュして、まだ通過できるようにするためです)。それらのいくつかは「不明」であるという情報について。

背景レベル 2

ライブラリが反復可能なオブジェクトの定義で使用するためにこのクラスを提供する状況を実際に空想している__len__ので、「最小」、「最大」、または「最良の推測」のいずれかに基づいて数値を返すことができますが、まだそうではありませんいくつかの単純な数学でさらに使用することに悩まされています。

>>> count = uint(100, 'minimum')
>>> print count
"minimum of 100"
>>> count * 20
2000
>>>

巨大なファイルを読み取る反復子を持つオブジェクトを想像してみてください。なぜオブジェクトは「まあ、ファイルは 400 MiB なので、少なくとも 4,000 レコードあるでしょう」と言うことができなかったのでしょうか?

おまけの質問: どちらが簡単ですか: int をサブクラス化するか、新しいクラスを作成しますが、算術演算用のインターフェイスを実装して維持する必要がありますか?

4

3 に答える 3

3

実装の問題に勝る概念的な問題がいくつかあると思います。

「不明な値」を 1 として扱うと、実際には不明ではなくなります。浮動小数点数との類似性を引き出すために、明確に定義された「非数」があり、これは数学演算に関与しますが、ほとんどの場合 NaN を生成します。例えば:

>>> f = float('NaN')
>>> 42 * f
nan

NaN は実際には数値ではないため、これを使用した算術演算は一見有効な結果を生成しないため、これは良いことです。提案どおりに「不明な整数」を実装した場合、不明な値は無意味な結果をもたらします。例えば:

>>> u = uint('unknown')
>>> 42 * u
42

適切な整数が返されますが、それは本当に必要なセマンティクスですか? 別の同様のケースは、数学的に定義されていないゼロによる除算です。所定の位置にこじ開けられる可能性のある値は、数学的な不条理をもたらします。(x/y) * y == x(場合に限り)あなたはそれy != 0を期待するかもしれません:

>>> (42 / 0) * 0   # this doesn't really work
42

しかし、数学を壊さずにそれを行うことはできません。

于 2013-09-23T19:10:27.350 に答える
2

なぜこれをしたいのか正確にはわかりませんが、次のように動作するはずです:

class uint(int):
    def __new__(cls, value):
        unknown = value == 'unknown'
        obj = super(uint, cls).__new__(cls, 1 if unknown else value)
        obj.unknown = unknown
        return obj

    def __str__(self):
        return 'unknown' if self.unknown else super(uint, self).__str__()

ここでの考え方は、 int 値を というプロパティに格納する代わりに、self.value使用したい値でスーパー クラスのインスタンス化を実行するというものです。

于 2013-09-23T19:05:14.877 に答える