0

まだPythonに少し難解であり、それは魔法の関数型プログラミングなので、慣用的PythonではなくプログラミングのJavaパラダイムに向かっているコードを書く傾向があります。 How do I make a custom class a collection in Pythonカスタムクラスのためのpythonコレクションの使い方

唯一の違いは、私が入れ子になってきているオブジェクト(組成物を使用):

私の質問は、多少に関係しています。 仮想ページオブジェクトは、物理ページオブジェクトのリストで構成されています。 PhyscialPageオブジェクトのリストを取得し、すべての詳細を単一の名前付きタプルにまとめる関数を持っています。PageBoundaryです。基本的には、ページ内の物理ページと行番号を表す整数範囲からなるタプルを吐き出すことができるシリアライズ関数です。このことから私は簡単にソートし、注文VirtualPages互いに(つまり、少なくともアイデアだ)の間ですることができます

PageBoundary = collections.namedtuple('PageBoundary', 'begin end') 

私もPageBoundary namedtupleを取り、にタプルをデシリアライズまたは拡張できる機能を持っています物理ページのリスト。これらの2つのデータストレージクラスは、下流のコードを壊すので変更しないことが望ましいです。

私のカスタムpython2.7クラスのスニペットです。

class VirtualPage(object): 
    def __init__(self, _physical_pages=list()): 
     self.physcial_pages = _physcial_pages 


class PhysicalPage(object): 
    # class variables: number of digits each attribute gets 
    _PAGE_PAD, _LINE_PAD = 10, 12 

    def __init__(self, _page_num=-1): 
     self.page_num = _page_num 
     self.begin_line_num = -1 
     self.end_line_num = -1 

    def get_cannonical_begin(self): 
     return int(''.join([str(self.page_num).zfill(PhysicalPage._PAGE_PAD), 
        str(tmp_line_num).zfill(PhysicalPage._LINE_PAD) ])) 

    def get_cannonical_end(self): 
     pass # see get_cannonical_begin() implementation 

    def get_canonical_page_boundaries(self): 
     return PageBoundary(self.get_canonical_begin(), self.get_canonical_end()) 

は、私は(Pythonのコレクションモジュールからの)いくつかのテンプレートコレクションを活用したいと思います簡単にソートし、リストと比較またはで設定するには:それは多くのもので構成されている1は、オブジェクトPhysicalPageを含むリストです仮想ページクラス。また、私のデータストレージクラスのレイアウトに関するいくつかのアドバイスがあります:仮想ページ物理ページ

VirtualPagesのいずれかの配列を考えると以下の例のように:それはあることは明らかと思われる右バット

>>> vp_2 in vp_1 
False 
>>> vp_2 < vp_1 
True 
>>> vp_1 == vp_1_copy 
True 

vp_1 = VirtualPage(list_of_physical_pages) 
vp_1_copy = VirtualPage(list_of_physical_pages) 
vp_2 = VirtualPage(list_of_other_physical_pages) 

私は簡単にこのような質問に答えるようにしたいですVirtualPageクラスは、get_cannonical_page_boundariesを呼び出すか、関数自体を実装する必要があります。最低でそれをループは、必要な機能を実装(LTを()と())するPhysicalPageリストだべきであるので、私は、B/W VirtualPagesを比較することができます。

1.)現在、私はいくつかの比較関数の実装に苦労しています。 1つの大きな障害はタプルをどのように比較するかです。

import collections as col 
import functools 

@total_ordering 
class AbstractVirtualPageContainer(col.MutableSet): 

    def __lt__(self, other): 
     '''What type would other be? 
     Make comparison by first normalizing to a comparable type: PageBoundary 
     ''' 
     pass 

2:私は、コレクションのいくつかのタイプを拡張するカスタムクラスを作成することで、私自身のLT()関数を作成してください。)代わりに、VirtualPageクラスに比較関数の実装が存在する必要がありますか?

私がモデル化しているデータのプロパティには一意性の概念があります。つまり、物理ページの値は重複できず、リンクされたリストとして機能するようになっています。また、@ decorator関数を介して実装されたsetter関数やgetter関数は、ここでの使用になりますか?

+0

「vp_2 in vp_1」とはどういう意味ですか?共通の物理ページが1つ以上あるか、またはvp_2のすべてのページもvp_1になっていますか? '<'、 '=='などの場合も同様です。これらの操作は、物理ページまたはPageBoundariesに関して定義されていますか?私は 'get_cannonical_begin()'を 'return self.page_num * 10 **に単純化することができると思います。012_物理的ページ._LINE_PAD + tmp_line_num' – RootTwo

+0

残念ながら入力してください。 ボリューム内の物理ページの初期セットから始めてください。** pp_init_set * *。私の目標は** page_ line_blickを** PhysicalPages **の形で定義して** ** pp_init_set **を異なる** VirtualPage **オブジェクトに分割することです。 私が終わったら、私は一意の** VirtualPage **オブジェクトのリストを設定しておくべきです。私がこの設定をまとめると、元の** pp_init_set **が得られるはずです。これは、欠落したページ(穴)も重複するページもないことを意味する。 仮想ページ[i] .physical_pages [-1] .end_line_num ==仮想ページ[i + 1] .physical_pages [0] .begin_line_num – Dave

+0

vp_1のvp_2はそれほど役に立ちません。私は本当にhttps://docs.python.org/2/library/collections.html?highlight=collections#collections-abstract-base-classes で十分な機能を定義して、自分のMutableSetを** VirtualPagesにしたいと思います**私は高レベルで、vp_2 - vp_1を実行して、差異を得ることができます。b/w ** VirtualPages **。この場合、私は暗黙のうちに**上記の2つのルールが有効な新しいVirtualPage **を取得することを期待します。 ** PageBoundaries **は、** PhysicalPages **のリストを表す単純な変換関数です。応答btwありがとう! – Dave

答えて

0

私はあなたが以下のコードのようなものを望むと思う。未検証;確かに

from collections import namedtuple 

# PageBoundary is a subclass of named tuple with special relational 
# operators. __le__ and __ge__ are left undefined because they don't 
# make sense for this class. 
class PageBoundary(namedtuple('PageBoundary', 'begin end')): 
    # to prevent making an instance dict (See namedtuple docs) 
    __slots__ =() 

    def __lt__(self, other): 
     return self.end < other.begin 

    def __eq__(self, other): 
     # you can put in an assertion if you are concerned the 
     # method might be called with the wrong type object 
     assert isinstance(other, PageBoundary), "Wrong type for other" 

     return self.begin == other.begin and self.end == other.end 

    def __ne__(self, other): 
     return not self == other 

    def __gt__(self, other): 
     return other < self 


class PhysicalPage(object): 
    # class variables: number of digits each attribute gets 
    _PAGE_PAD, _LINE_PAD = 10, 12 

    def __init__(self, page_num): 
     self.page_num = page_num 

     # single leading underscore is 'private' by convention 
     # not enforced by the language 
     self._begin = self.page_num * 10**PhysicalPage._LINE_PAD + tmp_line_num 
     #self._end = ...however you calculate this...     ^not defined yet 

     self.begin_line_num = -1 
     self.end_line_num = -1 

    # this serves the purpose of a `getter`, but looks just like 
    # a normal class member access. used like x = page.begin 
    @property 
    def begin(self): 
     return self._begin 

    @property 
    def end(self): 
     return self._end 

    def __lt__(self, other): 
     assert(isinstance(other, PhysicalPage)) 
     return self._end < other._begin 

    def __eq__(self, other): 
     assert(isinstance(other, PhysicalPage)) 
     return self._begin, self._end == other._begin, other._end 

    def __ne__(self, other): 
     return not self == other 

    def __gt__(self, other): 
     return other < self 


class VirtualPage(object): 
    def __init__(self, physical_pages=None): 
     self.physcial_pages = sorted(physcial_pages) if physical_pages else [] 

    def __lt__(self, other): 
     if self.physical_pages and other.physical_pages: 
      return self.physical_pages[-1].end < other.physical_pages[0].begin 

     else: 
      raise ValueError 

    def __eq__(self, other): 
     if self.physical_pages and other.physical_pages: 
      return self.physical_pages == other.physical_pages 

     else: 
      raise ValueError 

    def __gt__(self, other): 
     return other < self 

といくつかの観測など、YMMV、アプリケーションのか、あなたのデータをテストしていません:

「プライベート」のメンバーのようなものは、Pythonのクラスではありませんが、それが慣習です1つのアンダースコア(_)で変数名を開始すると、クラス/モジュール/などのパブリックインターフェイスの一部ではないことを示します。したがって、 '_'を含むパブリックメソッドの名前付けメソッドのパラメータは正しくないようですが、例えば、def __init__(self, _page_num=-1)

一般に、Pythonはsetter/gettersを使用しません。単に属性を直接使用してください。属性値を計算する必要がある場合やその他の処理が必要な場合は、上記のPhysicalPage.begin()のように@propertyデコレータを使用してください。

デフォルトの関数引数を可変オブジェクトで初期化することは、一般的にはお勧めできません。 def __init__(self, physical_pages=list())は毎回新しい空のリストでphysical_pagesを初期化しません。むしろ、毎回同じリストを使用します。リストが変更された場合、次の関数呼び出しで、physical_pagesは変更されたリストで初期化されます。 VirtualPages initializerを参照してください。

+0

ありがとう!私は間違いなくこれらのアイデアをたくさん使うことができます。また、デフォルトの引数と可変オブジェクトのおかげです。足で自分を撃ち、それを知らない本当に良い方法のように聞こえる。あなたの時間を感謝します! – Dave

関連する問題