假设以下代码:
import cv2 #3rd party python module (C extension!!)
a0 = cv2.KeyPoint(x=100,y=200,_size=20, _angle=1, _response=2, _octave=3, _class_id=4)
print "undesired output, desired syntax"
print a0
print str(a0)
print repr(a0)
print "desired output, undesired syntax"
print a0.pt, a0.size, a0.angle, a0.response, a0.octave, a0.class_id
其中打印出来:
undesired output, desired syntax
<KeyPoint 0x7fc2575a9a20>
<KeyPoint 0x7fc2575a9a20>
<KeyPoint 0x7fc2575a9a20>
desired output, undesired syntax
(100.0, 200.0) 20.0 1.0 2.0 3 4
如何使用所需的语法获得所需的输出?
据我所知,有以下方法:
从KeyPoint派生我自己的类并在那里实现str和repr:不需要的作为 a( cv2 中的某些函数需要 cv.KeyPoint 对象列表,转换会减慢代码速度 b( 额外的类层使代码更加复杂
猴子补丁关键点:会很好,但不起作用(请参阅下面的代码(。此外,我不知道 cv2 中期待 KeyPoint 列表的函数是否会接受这种修改后的类。
猴子补丁 A0:会不太好,但两者都不起作用(见下面的代码(。
为 CV2 类型的对象注册全局格式化函数。每当必须将此类对象转换为字符串时调用的 KeyPoint。(方法类似于用于泡菜序列化的 copyreg(。我没有发现任何暗示这样的注册表确实存在。
我的猴子补丁意图:
def custom_str(self):
return " ".join(self.pt, self.size, self.angle, self.response, self.octave, self.class_id)
try:
print "patching class"
cv2.KeyPoint.__str__ = custom_str
print str(a0)
a1 = cv2.KeyPoint(x=100,y=200,_size=20, _angle=1, _response=2, _octave=3, _class_id=4)
print str(a1)
except Exception, e:
print "failed"
print e
try:
print "patching object"
a0.__str__ = custom_str
print str(a0)
except Exception, e:
print "failed"
print e
输出:
patching class
failed
'builtin_function_or_method' object attribute '__str__' is read-only
patching object
failed
'cv2.KeyPoint' object attribute '__str__' is read-only
这在 REPL 中有效。
在一个模块(test.py(中,我有以下类:
class A(object):
def __init__(self):
self.a = 1
self.b = 2
在没有定义str的情况下,我在REPL中看到以下内容
>>> import test
>>> a=test.A()
>>> a
<test.A at 0x7fa4c327e450>
>>> str(a)
'<test.A object at 0x7fa4c327e450>'
然后我做了以下事情:
>>> def f(self) : return ",".join([str(self.a),str(self.b)])
>>> setattr(test.A, "__str__", f)
>>> str(a)
'1,2'
请注意,修补类会自动更新所有现有实例。
这将启用所需的"打印 a0"语法。
但是,如果由于与现有代码的潜在冲突而犹豫是否要替换魔术__str__方法,则可以使用此方法添加具有特定名称的新方法。
>>> setattr(test.A,"formatted", f)
>>> print a.formatted()
'1,2'