8

少しコードを試してみましたが、問題が発生しているようです:

class Page:
    cache = []


    """ Return cached object """
    def __getCache(self, title):
        for o in Page.cache:
            if o.__searchTerm == title or o.title == title:
                return o
        return None


    """ Initilize the class and start processing """
    def __init__(self, title, api=None):
        o = self.__getCache(title)
        if o:
            self = o
            return
        Page.cache.append(self)

        # Other init code
        self.__searchTerm = title
        self.title = self.someFunction(title)

それから私は試します:

a = Page('test')
b = Page('test')

print a.title # works
print b.title # AttributeError: Page instance has no attribute 'title'

このコードの何が問題なのですか? なぜ機能しないのですか?それを機能させる方法はありますか?そうでない場合、オブジェクトをキャッシュしているエンドユーザーに対して簡単かつ透過的に移動するにはどうすればよいですか?

4

3 に答える 3

10

作成を操作する場合は、変更する必要があります__new__

>>> class Page(object):
...     cache = []
...     """ Return cached object """
...     @classmethod
...     def __getCache(cls, title):
...         for o in Page.cache:
...             if o.__searchTerm == title or o.title == title:
...                 return o
...         return None
...     """ Initilize the class and start processing """
...     def __new__(cls, title, api=None):
...         o = cls.__getCache(title)
...         if o:
...             return o
...         page = super(Page, cls).__new__(cls)
...         cls.cache.append(page)
...         page.title = title
...         page.api = api
...         page.__searchTerm = title
...         # ...etc
...         return page
... 
>>> a = Page('test')
>>> b = Page('test')
>>> 
>>> print a.title # works
test
>>> print b.title
test
>>> 
>>> assert a is b
>>> 

編集:使用__init__

>>> class Page(object):
...     cache = []
...     @classmethod
...     def __getCache(cls, title):
...         """ Return cached object """
...         for o in Page.cache:
...             if o.__searchTerm == title or o.title == title:
...                 return o
...         return None
...     def __new__(cls, title, *args, **kwargs):
...         """ Initilize the class and start processing """
...         existing = cls.__getCache(title)
...         if existing:
...             return existing
...         page = super(Page, cls).__new__(cls)
...         return page
...     def __init__(self, title, api=None):
...         if self in self.cache:
...             return
...         self.cache.append(self)
...         self.title = title
...         self.api = api
...         self.__searchTerm = title
...         # ...etc
... 
>>> 
>>> a = Page('test')
>>> b = Page('test')
>>> 
>>> print a.title # works
test
>>> print b.title
test
>>> assert a is b
>>> assert a.cache is Page.cache
>>> 
于 2012-10-24T17:31:01.933 に答える
4

一度作成されたオブジェクトのインスタンスを実際に変更することはできません。self他の何かに設定するときは、変数が指す参照を変更するだけなので、実際のオブジェクトには影響しません。

titleこれは、属性が存在しない理由も説明しています。ローカルself変数を変更するとすぐに戻り、現在のインスタンスがtitle初期化された属性を取得できないようにします (selfその時点で正しいインスタンスを指していないことは言うまでもありません)。

そのため、基本的に、初期化中 ( ) にオブジェクトを変更することはできません。__init__その時点では、オブジェクトは既に作成され、変数に割り当てられているためです。次のようなコンストラクター呼び出しa = Page('test')は、実際には次と同じです。

a = Page.__new__('test')
a.__init__('test')

ご覧のとおり、__new__クラス コンストラクターが最初に呼び出され、それが実際にインスタンスの作成を担当します。したがって、クラスの__new__メソッドを上書きして、オブジェクトの作成を操作できます。

ただし、一般的に推奨される方法は、次のような単純なファクトリ メソッドを作成することです。

@classmethod
def create (cls, title, api = None):
    o = cls.__getCache(title)
    if o:
        return o
    return cls(title, api)
于 2012-10-24T17:22:59.867 に答える
1

selfは通常のローカル変数であるため、設定は変数がその関数内で指すself = ..ものを変更するだけです。実際のオブジェクトは変更されません。self

参照:メソッド内で自己オブジェクトを同じ型の別のオブジェクトに置き換えても安全ですか?

必要なことを行うには、 static 関数をfactoryとして使用できます。

class Page:
    cache = []


    """ Return cached object """
    @staticmethod
    def create(title):
        for o in Page.cache:
            if o.__searchTerm == title or o.title == title:
                return o
        return Page(title)

    """ Initilize the class and start processing """
    def __init__(self, title, api=None):
        Page.cache.append(self)

        # Other init code
        self.__searchTerm = title
        self.title = title


a = Page.create('test')
b = Page.create('test')

print a.title
print b.title
于 2012-10-24T17:15:39.987 に答える