我试图在新的样式类中拦截对python的双下划线魔术方法的调用.这是一个简单的例子,但它显示了意图:
class ShowMeList(object):
def __init__(self, it):
self._data = list(it)
def __getattr__(self, name):
attr = object.__getattribute__(self._data, name)
if callable(attr):
def wrapper(*a, **kw):
print "before the call"
result = attr(*a, **kw)
print "after the call"
return result
return wrapper
return attr
Run Code Online (Sandbox Code Playgroud)
如果我在列表周围使用该代理对象,我会获得非魔术方法的预期行为,但我的包装函数永远不会被魔术方法调用.
>>> l = ShowMeList(range(8))
>>> l #call to __repr__
<__main__.ShowMeList object at 0x9640eac>
>>> l.append(9)
before the call
after the call
>> len(l._data)
9
Run Code Online (Sandbox Code Playgroud)
如果我不从对象继承(第一行class ShowMeList:),一切都按预期工作:
>>> l = ShowMeList(range(8))
>>> l #call to __repr__
before the call …Run Code Online (Sandbox Code Playgroud) 我在将对象的实例变量传递给实例方法时遇到问题。
我已经在其他地方搜索过这个,但我一直找到的只是有关如何使用我已经知道的将对象传递给方法的信息self,或者只是关于类和实例方法之间的一般差异的教程,这些差异没有具体回答我的问题。我的问题的答案肯定存在于某个地方,我想我只是不知道实际要问什么。
在我的代码中,我有这个类:
class SongData:
def __init__(self, datapoint):
self.artist = datapoint['artist']
self.track = datapoint['name']
def xtradata_rm(self, regex, string=None):
if string is None:
string = self
srchrslts = re.search(regex, string)
if srchrslts is not None:
if regex == 'f.*?t':
self = self.replace(string,'')
self.xtradata_rm('\((.*?)\)')
else:
self.xtradata_rm('f.*?t', srchrslts)
def example_method(self):
#This one isn't actually in the code, included for ease of explanation.
print(self)
#some more methods irrelevant to question down here.
Run Code Online (Sandbox Code Playgroud)
想象一下我们通过执行以下操作来实例化一个对象song = SongData(datapoint)。该方法xtradata_rm应该在 或song.artist字符串中搜索 …
我想让字符串比较不区分大小写。为此,我想创建一个只有一个字符串字段的不可变类。在构造函数中,我想在将值分配给字段之前调用 lower() 。
我想尽可能多地使用标准类,如命名元组或数据类。使用该__post_init__函数(参见例如如何在Python中的数据类中使用__post_init__方法)感觉就像是一种黑客攻击。这也让我想知道在我在函数中更改它后该字段是否仍然冻结__post_init__。
但是,我找不到__pre_init__功能。有没有更好的办法?