簡體   English   中英

是否可以覆蓋“self”以指向 python 中 self.method 中的另一個對象?

[英]is it possible to overwrite “self” to point to another object inside self.method in python?

class Wrapper(object):
    def __init__(self, o):
        # get wrapped object and do something with it
        self.o = o
    def fun(self, *args, **kwargs):
        self = self.o # here want to swap
        # or some low level C api like
        # some_assign(self, self.o)
        # so that it swaps id() mem addr to self.o
        return self.fun(*args, **kwargs) # and now it's class A

class A(object):
    def fun(self):
        return 'A.fun'

a = A()
w = Wrapper(a)
print type(w) # wrapper
print w.fun() # some operation after which I want to loose Wrapper
print a is w # this goes False and I'd like True :) 
             # so that this is the original A() object 

有沒有辦法在 Python 中做到這一點?

在方法內賦值給self只是將局部變量self重新綁定到新對象。 通常,對裸名稱的賦值永遠不會改變任何對象,它只是重新綁定左側的名稱以指向右側的對象。

因此,您需要做的是修改self指向的對象以匹配self.o指向的對象。 這只有在AWrapper都是新式類並且它們都沒有定義__slots__才有可能:

self.__class__ = self.o.__class__
self.__dict__ = self.o.__dict__

這將在 CPython 中工作,但我不確定其他 Python 實現。 即使在 CPython 中,這樣做也是一個糟糕的主意。

(請注意,代碼最后一行中的is條件仍將是False ,但我認為這符合您的意圖。)

不,你不能。 這將需要通過引用傳遞。 您可以更改局部變量(更准確地說,參數) self就好了,但是這樣做不會影響作為參數傳遞的引用來自的任何位置(例如您的w )。

考慮到情況(隱式傳遞self ),甚至不可能應用通常的技巧(例如使用單元素列表和變異x[0] )。 即使這樣的技巧會奏效(或者如果有更晦澀的黑客可以做到這一點),他們也會非常氣餒。 它與 Python 程序員習慣的一切背道而馳。 只需讓Wrapper對象表現得好像它被替換(即,將所有內容轉發到self.o )。 這不會使身份檢查成功,但它是迄今為止最簡單、最干凈和最易於維護的解決方案。

注意:為了試驗,有一個非標准且絕對不可移植的 PyPy 擴展可以做到這一點(完全替換一個對象): __pypy__.become 不用說,使用它是非常不明智的。 尋找另一個解決方案。

您已經覆蓋了自己,但更改僅在fun()中本地有效。 我添加了幾個打印輸出來試試:

    def fun(self, *args, **kwargs):
    print self, self.o
    self = self.o # here want to swap
    print self, self.o

輸出顯示原始Wrapper和A in self和self.o,然后是A和traceback,因為self.o在A類中無效。

<__main__.Wrapper object at 0xb77be38c> <__main__.A object at 0xb77be34c>
<__main__.A object at 0xb77be34c>
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/tmp/python-2803VQb.py", line 21, in <module>
    print w.fun() # some operation after which I want to loose Wrapper
  File "/tmp/python-2803VQb.py", line 8, in fun
    print self, self.o
AttributeError: 'A' object has no attribute 'o'

改變自我和副作用是不好的。 為什么不直接在調用代碼中分配給w:

print w.fun() # some operation after which I want to loose Wrapper
w = a         # Sure you will loose the Wrapper
print a is w # this goes False and I'd like True :) 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM