正如其他用户指出的那样,Python 的核心类型在设计上是不可变的:
>>> int.frobnicate = lambda self: whatever()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'int'
您当然可以通过创建子类来实现您描述的效果,因为 Python 中的用户定义类型默认情况下是可变的。
>>> class MyInt(int):
... def frobnicate(self):
... print 'frobnicating %r' % self
...
>>> five = MyInt(5)
>>> five.frobnicate()
frobnicating 5
>>> five + 8
13
也没有必要MyInt
公开子类;也可以直接在构造实例的函数或方法中内联定义它。
在某些情况下,精通该习语的 Python 程序员会认为这种子类化是正确的做法。例如,os.stat()
返回一个tuple
添加命名成员的子类,正是为了解决您在示例中提到的那种可读性问题。
>>> import os
>>> st = os.stat('.')
>>> st
(16877, 34996226, 65024L, 69, 1000, 1000, 4096, 1223697425, 1223699268, 1223699268)
>>> st[6]
4096
>>> st.st_size
4096
也就是说,在您给出的具体示例中,我不相信(或其他地方)的子类float
化item.price
很可能被认为是 Pythonic 的事情。如果这是主要用例,我可以很容易地想象有人决定添加一个price_should_equal()
方法;item
如果人们正在寻找更一般的东西,也许使用命名参数来使预期的含义更清晰可能更有意义,例如
should_equal(observed=item.price, expected=19.99)
或类似的规定。它有点冗长,但毫无疑问它可以改进。与 Ruby 风格的猴子补丁相比,这种方法的一个可能优势是should_equal()
可以轻松地对任何类型进行比较,而不仅仅是int
or float
。但也许我过于关注您碰巧提供的特定示例的细节。