【发布时间】:2010-12-24 23:09:11
【问题描述】:
这是我想做的模型:
alist = [1,2,3,4,5] # create a vanilla python list object
replacef (alist) # replace __setitem__, extend,... with custom functions
alist[0]=2 # now the custom __setitem__ is called
这适用于语法应尽可能接近普通 python 的 DSL 项目,因此子类化列表并让用户调用类似 alist = MyList(1,2,3,4,5) 的东西是不可取的。此外,由于 DSL 需要与其他库共存,全局更改 list 和 dict 不是一种选择...
我尝试过创建实例方法并将它们直接设置在 alist.append = myFunc 之类的对象上,但 Python 表示这些属性是只读的。更改__class__ 属性似乎也是不允许的。
我正在尝试做的事情在 Python 中是否可行?
更新:以下是关于对象子类的一些发现:
给定:
class y(object):
def __init__(self,a,b,c):
self.a = a
self.b = b
self.c = c
def f(self):
print self
print self.a
print self.b
print self.c
class x(object):
def __init__(self,a,b,c):
self.a = a
self.b = b
self.c = c
def f(self):
print "x.f()"
>>> objy = y(1,2,3)
>>> objx = x(4,5,6)
>>> objy.f()
<__main__.y object at 0x02612650>
1
2
3
>>> objx.f()
x.f()
可以像这样动态更改 objx 的类:
>>> objx.__class__ = y
>>> objx.f()
<__main__.y object at 0x02612D90>
4
5
6
此外,可以动态添加/更改对象方法,就像在 javascript 中一样:
>>> def g(self,p):
print self
print p
>>> import new
>>> objy.g = new.instancemethod(g,objy,y)
>>> objy.g(42)
<__main__.y object at 0x02612650>
42
但是,对于用 C 语言实现的对象(如 dict 和 list),这两种方法都会失败:
>>> def mypop(self):
print "mypop"
list.mypop(self)
>>> alist.pop = new.instancemethod(mypop,alist,list)
AttributeError: 'list' object attribute 'pop' is read-only
>>> x = [1,2,3,4,5]
>>> x.__class__ = mylist
TypeError: __class__ assignment: only for heap types
建议的使用类似 alist = replacef(alist) 的方法在这里不起作用,因为可以像这样从 __setattribute__ 调用中调用 replacef:
alist = [1,2,3,4,5]
aDSLObject.items = alist # __setattribute__ calls replacef on alist
alist[0] = ....
因此,虽然确实可以动态更改对象方法,但似乎无法更改用 C 实现的对象的行为 - 还是我遗漏了什么?
【问题讨论】:
标签: python list dynamic methods dictionary