[英]Python inherit magic methods based off __init__ value
讓我們想象一下,我有一個單一的 X
級。 X
的目的是包裝list
或dict
並提供事件監聽功能。 一切順利。
class X(object):
def __init__(self, obj)
self._obj = obj
def __getattr__(self, name):
# do stuff with self._obj
def __getitem__(self, key):
return self._obj[key]
def __setitem__(self, key, val):
self._obj[key] = val
# rest of functionality ...
所以這可以用來包裝像這樣的dict
:
x = X({
'foo' : False
})
x.listen('foo', callback)
X['foo'] = True # triggers event
X.update({
'foo' : False # triggers event
})
或者list
:
x = X([1,2])
x.listen(callback)
X.append(1) # triggers event
X[0] = 10 # triggers event
大。 幾乎是我想要完成的......
現在的問題是,因為X
同時適用於list
和dict
對象,所以它不能繼承。 這意味着我沒有魔術類函數,例如__contains__
。
這導致這樣的代碼
d = X({
'foo' : True
})
if 'foo' in d:
print 'yahoo!'
拋出KeyError
。
如何在不定義X
內部所需的每種魔法的情況下解決這個問題。 如果我這樣做,對於每個定義,我將根據self._obj
是list
還是dict
來編寫兩個返回值。
我認為我最初可以用元類做這個,但這似乎不是一個解決方案,因為我需要訪問傳遞的值來檢查它是否是一個dict
或list
。
一種簡單的方法是使用代理類,例如wrapt.ObjectProxy
。 除了重寫的方法之外,它的行為與“代理”類完全相同。 但是,您可以簡單地使用self.__wrapped__
來訪問“unproxied”對象,而不是self._obj
。
from wrapt import ObjectProxy
class Wrapper(ObjectProxy):
def __getattr__(self, name):
print('getattr')
return getattr(self.__wrapped__, name)
def __getitem__(self, key):
print('getitem')
return self.__wrapped__[key]
def __setitem__(self, key, val):
print('setitem')
self.__wrapped__[key] = val
def __repr__(self):
return repr(self.__wrapped__)
如果你包裝一個字典,這就像一個字典:
>>> d = Wrapper({'foo': 10})
>>> d['foo']
getitem
10
>>> 'foo' in d # "inherits" __contains__
True
並且像列表一樣,如果列表被包裝:
>>> d = Wrapper([1,2,3])
>>> d[0]
getitem
1
>>> for i in d: # "inherits" __iter__
... print(i)
1
2
3
您可以使用集合中的 UserList
或UserDict
from collections import UserList
class X(UserList):
def __init__(self, obj):
super().__init__()
self.data = obj
def __getattr__(self, name):
pass
# do stuff with self.data
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, val):
self.data[key] = val
x0 = X([1, 2, 3])
x1 = X({1, 2, 3})
x2 = X({1: 1, 2: 2})
print(1 in x0)
print(1 in x1)
print(1 in x2)
嘗試類似的東西
def contains (self, item):
If isinstance (self._obj, list):
return list.contains (self._obj, item)
If isinstance (self._obj, dict):
return dict.contains (self._obj, item)
或者你想要繼承什么方法。 調用實例方法時,實例將自動與self一起傳遞。 但是如果從類去除中調用該方法,則需要傳遞一個對象,因為self需要一個值。
Class Test:
def print_cls (self):
print self.__class__.__name__
t = Test ()
t.print_cls () # self is teat
Test.print_cls (5)
# we replace self with another class object
# as long as the object you pass has the
# variables used in the method you call all should be good.
這將打印出Test
和int
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.