下面是我想做的一个模型:
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
这是一个DSL项目,其中的语法应该尽可能接近普通python,因此子类化list并让用户调用alist=MyList(1,2,3,4,5)是不可取的。另外,由于DSL需要与其他库共存,全局更改list和dict不是一个选项。。。在
我尝试过创建instancemethods并将它们直接设置在对象上,比如列表.append=myFunc,但Python说这些属性是只读的。似乎也不允许更改__class__
属性。在
我想在Python中做的事情是可能的吗?在
更新:下面是一些关于object的子类可能的发现:
给予:
^{pr2}$可以像这样动态更改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)的方法在这里行不通,因为replacef可以从__setattribute__
调用中调用,如下所示:
alist = [1,2,3,4,5]
aDSLObject.items = alist # __setattribute__ calls replacef on alist
alist[0] = ....
因此,虽然可以动态地更改对象方法,但似乎不可能更改用C实现的对象的行为,或者我遗漏了什么?在
“显式比隐式好。”您应该只记录用户需要使用}。从长远来看,你和你的用户会更快乐。在
MyList()
而不是{顺便说一句,Ruby允许你想要什么。使用Ruby,您可以打开全局对象并添加新的行为。我觉得这很可怕,而且Ruby的运行速度比Python慢,所以我实际上并没有敦促您改用Ruby。在
因此,请提供
MyList()
,并提供一种方法来获取现有列表并将其包装在MyList()
中。在您可以编写
MyList()
来获取一组参数,并非常方便地列出一个列表:然后可以用
MyList(1, 2, 3, 4)
调用它,实例将有一个名为lst的成员,其值为:[1, 2, 3, 4]
但是现在,如果您想从一个列表中创建一个
^{pr2}$MyList
实例,该如何实现呢?如果您这样做:那么您只需将x设置为:
[[1, 3, 5]]
因此,我建议您使
MyList()
只需获取一个列表参数并保存它:我刚刚编辑了这个答案。最初,我有一个对
list()
的调用,现在我已经调用了ensure_list()
。ensure_list()
检查是否可以为其参数编制索引;如果可以,则它要么是一个列表,要么是一个类似于列表的东西,并且返回时没有改变。如果您不能索引它,那么ensure_list()
调用list(seq)
来尝试将其转换为一个列表。这将使用迭代器和生成器,迫使它们展开到列表中。在也许您可以在
replaceref
函数中执行“alist=MyList(1,2,3,4,5)”的操作?在{/strong>当一个标准的调用后,用户仍然会使用一个新的列表。在
相关问题 更多 >
编程相关推荐