我正在尝试在Python中扩展一些“基础”类:
class xlist (list):
def len(self):
return len(self)
def add(self, *args):
self.extend(args)
return None
class xint (int):
def add(self, value):
self += value
return self
x = xlist([1,2,3])
print x.len() ## >>> 3 ok
print x ## >>> [1,2,3] ok
x.add (4, 5, 6)
print x ## >>> [1,2,3,4,5,6] ok
x = xint(10)
print x ## >>> 10 ok
x.add (2)
print x ## >>> 10 # Not ok (#1)
print type(x) ## >>> <class '__main__.xint'> ok
x += 5
print type(x) ## >>> <type 'int'> # Not ok (#2)
它在 list 的情况下工作正常,因为 append 方法“就地”修改了对象,而没有返回它。但在 int 情况下, add 方法不会修改外部 x 变量的值。我认为 self 是类的 add 方法中的局部变量,这是好的,但这阻止我修改分配给实例的初始值上课。
是否可以通过这种方式扩展类,还是应该使用基类型定义类属性并将所有需要的方法映射到此属性?
答案 0 :(得分:23)
您的两个xint
示例由于两个不同原因而无效。
第一个不起作用,因为self += value
等同于self = self + value
,它只是将局部变量self
重新分配给另一个对象(整数),但不会更改原始对象。你无法真正得到这个
>>> x = xint(10)
>>> x.add(2)
使用int
的子类,因为整数是immutable。
要使第二个工作正常,您可以定义__add__
method,如下所示:
class xint(int):
def __add__(self, value):
return xint(int.__add__(self, value))
>>> x = xint(10)
>>> type(x)
<class '__main__.xint'>
>>> x += 3
>>> x
13
>>> type(x)
<class '__main__.xint'>
答案 1 :(得分:5)
int 是一种值类型,因此每次执行赋值时(例如,上面的 + = 的两个实例),它都不会修改您拥有的对象在堆上,但用赋值右边的结果之一替换引用(即int)
列表不是值类型,因此不受相同规则的约束。
此页面详细介绍了差异:http://docs.python.org/ref/objects.html
IMO,是的,你应该定义一个新的类,它将int保存为实例变量
答案 2 :(得分:2)
我稍微扩展了你的xlist类,这样你就可以找到一个数字的所有索引点,这样你就可以一次扩展多个列表,使它初始化并制作它以便你可以迭代它
class xlist:
def __init__(self,alist):
if type(alist)==type(' '):
self.alist = [int(i) for i in alist.split(' ')]
else:
self.alist = alist
def __iter__(self):
i = 0
while i<len(self.alist):
yield self.alist[i]
i+=1
def len(self):
return len(self.alist)
def add(self, *args):
if type(args[0])==type([1]):
if len(args)>1:
tmp = []
[tmp.extend(i) for i in args]
args = tmp
else:args = args[0]
if type(args)==type(''):args = [int(i) for i in args.split(' ')]
(self.alist).extend(args)
return None
def index(self,val):
gen = (i for i,x in enumerate(self.alist) if x == val)
return list(gen)
答案 3 :(得分:0)
Int是不可变的,你不能在适当的位置修改它们,所以你应该使用选项#2(因为没有一些技巧就不可能选择#1)。