我想创建一个类,如果继承任何其他兄弟类将设置一个' origin'实例上的属性。另一个兄弟类可能是可变的或不可变的。
我已经部分工作了。
class MyOrigin(object):
def __new__(cls, *args, **kwargs):
origin = kwargs.get('origin')
if 'origin' in kwargs:
del kwargs['origin']
obj = super(MyOrigin, cls).__new__(cls, *args, **kwargs)
obj.origin = origin
return obj
def __init__(self, *args, **kwargs):
origin = kwargs.get('origin')
if 'origin' in kwargs:
del kwargs['origin']
super(MyOrigin, self).__init__(*args, **kwargs)
self.origin = origin
class MyListWithOrigin(MyOrigin, type(list())):
pass
# This works correctly
class MyDictWithOrigin(MyOrigin, type(dict())):
pass
# This works correctly too
class MyStringWithOrigin(MyOrigin, str):
pass
# This doesnt work if MyOrigin defines __init__
基本上,如果我在__init__
上定义MyOrigin
,那么super(MyOrigin, self).__init__
会尝试调用object.__init__
(因为str是不可变的,所以没有str.__init__
1}})第一个参数失败并且TypeError
为object.__init__
并不参与。
目前,我创建了两个类(MyOriginMutable和MyOriginImmutable),并在创建MyStrWithOrigin或MyListWithOrigin等时从中进行选择。是否有某种方法可以检测哪个类super()
从运行之前获取方法,以便我可以检测到并且不用args调用object.__init__
。
为清楚起见,这个例子有效,但是有没有办法在没有两个独立的Mutable和Immutable类的情况下做到这一点?
class MyOriginImmutable(object):
def __new__(cls, *args, **kwargs):
origin = kwargs.get('origin')
if 'origin' in kwargs:
del kwargs['origin']
obj = super(MyOriginImmutable, cls).__new__(cls, *args, **kwargs)
obj.origin = origin
return obj
class MyOriginMutable(object): # Edited so that it DOES NOT inherit from MyOriginImmutable
def __init__(self, *args, **kwargs):
# We define __init__ only for mutable classes
origin = kwargs.get('origin')
if 'origin' in kwargs:
del kwargs['origin']
super(MyOriginMutable, self).__init__(*args, **kwargs)
self.origin = origin
class MyOriginString(MyOriginImmutable, str):
"""A custom string class to hold origin"""
pass
class MyOriginList(MyOriginMutable, type(list())):
"""A custom list class to hold origin"""
pass
class MyOriginDict(MyOriginMutable, type(dict())):
"""A custom dict class to hold origin"""
pass
if __name__ == '__main__':
# Testing
try:
line = MyOriginString('some string', origin=('somewhere',))
print(line)
assert line.origin == ('somewhere',)
assert line == 'some string'
except Exception as e:
print("String like failed")
# raise e
try:
list_like = MyOriginList(['some', 'list'], origin=('somewhere',))
print(list_like)
assert list_like.origin == ('somewhere',)
assert list_like == ['some', 'list']
except Exception as e:
print("List like failed")
# raise e
try:
dict_like = MyOriginDict({'some': 'dict'}, origin=('somewhere',))
print(dict_like)
assert dict_like.origin == ('somewhere',)
assert dict_like == {'some': 'dict'}
except Exception as e:
print("Dict like failed")
raise e