【发布时间】:2016-01-09 19:55:02
【问题描述】:
我正在尝试“猴子补丁”列表的实例。请注意,这不是 my 列表。我无法控制它的创建。据我所知,这在 2.7 中是不可能的。我对吗? 3.x可以吗?
【问题讨论】:
标签: python list monkeypatching
我正在尝试“猴子补丁”列表的实例。请注意,这不是 my 列表。我无法控制它的创建。据我所知,这在 2.7 中是不可能的。我对吗? 3.x可以吗?
【问题讨论】:
标签: python list monkeypatching
不,您不能在 list 对象上添加或删除属性,在 Python 2 和 Python 3 中都不能。
您最多可以将这样的对象包装在另一个实例中,该实例实现与列表相同的属性和方法,但将对这些对象的访问权传递给包装的列表对象。
该包装器可以使用UserList.UserList() class 实现:
try:
# Python 2
from UserList import UserList
except ImportError:
# Python 3
from collections import UserList
class ListWrapper(UserList):
def extra_method(self):
return """Hi! I'm an extra method on this "list" (wink, wink)"""
演示:
>>> some_list = ['foo', 'bar', 'baz']
>>> wrapped_list = ListWrapper(some_list)
>>> len(wrapped_list)
3
>>> wrapped_list[1]
'bar'
>>> wrapped_list.extra_method()
'Hi! I\'m an extra method on this "list" (wink, wink)'
【讨论】:
UserList比list有什么优势?
list子类化,任何返回新实例(例如连接)的方法或运算符都会再次返回常规list对象,而UserList子类将始终返回而是包装类。
__getitem__ 方法直接委托给self.data.__getitem__。这很容易解决,但考虑到 __add__ 和 __mul__ 返回该类的一个实例,这仍然是出乎意料的。
__getslice__ 方法。但是 Python 3 完全删除了它(因为 __getitem__ 足以处理使用 slice() 对象的所有切片)。这确实是一个错误。
这是一种轻量级的方法,可以将单个方法添加到list 的子类的单个实例中
>>> import new
>>> L = ['f', 'o', 'o']
>>> M = type("list", (list, ), {})(L)
>>> M.bar = new.instancemethod(lambda self: self * 2, M)
>>> M.bar()
['f', 'o', 'o', 'f', 'o', 'o']
【讨论】:
M + ['foo'] 返回一个常规的list 对象。