Python 如何设置一个包含所有方法和函数的类,比如内置的float,但保留额外的数据?
我正在处理大约100000个值的2个数据集。这两个数据集只是列表。列表中的每个项目都是一个小类Python 如何设置一个包含所有方法和函数的类,比如内置的float,但保留额外的数据?,python,class,inheritance,floating-point,data-extraction,Python,Class,Inheritance,Floating Point,Data Extraction,我正在处理大约100000个值的2个数据集。这两个数据集只是列表。列表中的每个项目都是一个小类 class Datum(object): def __init__(self, value, dtype, source, index1=None, index2=None): self.value = value self.dtype = dtype self.source = source self.index1 = inde
class Datum(object):
def __init__(self, value, dtype, source, index1=None, index2=None):
self.value = value
self.dtype = dtype
self.source = source
self.index1 = index1
self.index2 = index2
对于一个列表中的每个数据,另一个列表中有一个匹配的数据,该数据具有相同的数据类型、源、index1和index2,我使用它对两个数据集进行排序,使它们对齐。然后,我对匹配数据点的值执行各种工作,这些值总是浮动的
目前,如果我想确定一个数据集中浮点数的相对值,我会这样做
minimum = min([x.value for x in data])
for datum in data:
datum.value -= minimum
minimum = min(data)
data = [x - minimum for x in data]
然而,让我的自定义类从float继承并能够像这样工作会很好
minimum = min([x.value for x in data])
for datum in data:
datum.value -= minimum
minimum = min(data)
data = [x - minimum for x in data]
我尝试了以下方法
class Datum(float):
def __new__(cls, value, dtype, source, index1=None, index2=None):
new = float.__new__(cls, value)
new.dtype = dtype
new.source = source
new.index1 = index1
new.index2 = index2
return new
但是,
data = [x - minimum for x in data]
删除所有额外属性(dtype、source、index1、index2)
我应该如何设置一个类,该类的功能类似于一个float,但保留我实例化它时使用的额外数据
更新:除了减法之外,我还做很多类型的数学运算,因此重写所有使用浮点运算的方法都会非常麻烦,坦率地说,我不确定我是否能正确重写它们。问题是当你这样做时:
x - minimum
就您正在执行的类型而言:
datum - float, or datum - integer
无论哪种方式,python都不知道如何执行这两种操作,所以如果可以的话,它所做的就是查看参数的父类。因为基准是一种浮点类型,所以它可以很容易地使用浮点-并且计算结果是
float - float
这显然会导致“float”——除非您告诉它,否则python无法知道如何构造数据对象
要解决这个问题,您需要实现数学运算符,以便python知道如何执行datum-float
,或者提出不同的设计
假设“dtype”、“source”、index1和index2在计算后需要保持不变,那么作为示例,您的类需要:
def __sub__(self, other):
return datum(value-other, self.dtype, self.source, self.index1, self.index2)
这应该是有效的-不需要测试
这将允许你这样做
d = datum(23.0, dtype="float", source="me", index1=1)
e = d - 16
print e.value, e.dtype, e.source, e.index1, e.index2
这将导致:
7.0 float me 1 None
我建议对float进行子类化,并使用一对修饰符“捕获”任何方法的float输出(当然,除了
\uuu new\uuu
),然后返回数据对象,而不是float
对象
首先,我们编写方法decorator(下面实际上没有将其用作decorator,它只是一个修改另一个函数(也称为包装函数)输出的函数):
第一个装饰器仅适用于它所附加的方法。但我们希望它装饰从float
继承的所有(实际上,几乎所有)方法(不管怎样,那些出现在float的\uuuu dict\uuuu
中的方法)。第二个修饰符将我们的第一个修饰符应用于float子类中的所有方法,除了列为exceptions()的方法外:
现在,我们编写的子类与您以前编写的子类基本相同,但是经过修饰,并且从修饰中排除\uuuu new\uuuu
(我想我们也可以排除\uuuu init\uuuu
,但是\uuuu init\uuuuuu
不会返回任何内容):
以下是我们的测试程序;迭代似乎工作正常:
d1 = Datum(1.5)
d2 = Datum(3.2)
d3 = d1+d2
assert d3.source == 'source'
L=[d1,d2,d3]
d4=max(L)
assert d4.source == 'source'
L = [i for i in L]
assert L[0].source == 'source'
assert type(L[0]) == Datum
minimum = min(L)
assert [x - minimum for x in L][0].source == 'source'
注:
- 我正在使用Python3。不确定这是否会对你产生影响李>
- 这种方法有效地覆盖了除异常之外的所有float方法,即使是结果未被修改的方法。这可能会有副作用(对内置函数进行子类化,然后覆盖它的所有方法),例如性能问题或其他问题;我真的不知道李>
- 这也将装饰嵌套类
- 同样的方法也可以使用元类实现李>
您可能需要定义所有的数学方法,以便任何数学运算产生的结果都是一个基准,而不是一个浮点。假设在您进行计算时,dtype、source、index1和index2不会发生变化,那么我的答案应该是有效的。在您的案例中,额外的方法并不复杂。
d1 = Datum(1.5)
d2 = Datum(3.2)
d3 = d1+d2
assert d3.source == 'source'
L=[d1,d2,d3]
d4=max(L)
assert d4.source == 'source'
L = [i for i in L]
assert L[0].source == 'source'
assert type(L[0]) == Datum
minimum = min(L)
assert [x - minimum for x in L][0].source == 'source'