我希望始终将类的实例视为其实例之一,除非特别要求其他属性。例如,假设我的课是:
class Value:
def __init__(self, value, description):
self.value = value
self.description = description
使得value
是一个浮点数,而description
是一个字符串。现在,除非特别要求Value
,否则我想始终将Instance.value
的实例视为Instance.description
。
我知道两种解决方案。第一种是通过以下方式在类中实现数字仿真:
def __add__(self, other):
return self.value + other
用于每种可能的数值运算。但是,这似乎过于繁琐-如果有人想使用Value实例来乘以一个列表,又会出现什么错误消息,以及在类实例而不是基本float上进行操作的所有其他方式会出错吗?我真的必须针对每种可能的操作案例引入类方法吗?
第二种解决方案是通过以下方式重新定义内容:
class Value(float):
pass
value1 = Value(8.0)
value1.description = 'The first value'
value2 = Value(16.3)
value2.description = 'The second value'
...
...
现在,该实例只是浮点值,并且说明已进行了硬编码。但这似乎也很繁琐,而且具有非Pythonic的特性。
我是否为此错过了一种非常简单的方法?还是我可以滑动的某个布尔标志?对于Python来说,似乎常常需要一种方法。
答案 0 :(得分:1)
“简单的解决方案”是您的第二个答案-子类,无论您尝试使用的值是什么。您仍然可以覆盖__init__
并添加所需的任何实体(尽管您还必须覆盖__new__
-请参见this answer):
class Value(float):
def __new__(self, value, description=''):
return float.__new__(self, value)
def __init__(self, value, description=''):
# let the superclass construct itself
float.__init__(value)
# give self a description
self.description = description
value1 = Value(8.0, 'the first value')
value2 = Value(16.3, 'the second value')
print(value1 + value2) # 24.3
print(value1 * value2) # 130.4
print(value1.description) # the first value
print(value2.description) # the second value
这与您第一个可能的解决方案基本相同,除了float
已经已经定义了所有算术运算符,而您只是继承了它。缺点是浮点数是不可变的,因此创建对象后就无法更改其值。
也许也可以创建一个装饰器来执行此操作,但这会更加复杂。