Ruby可以向Number类和其他核心类型添加方法以获得如下效果:
1.should_equal(1)
Run Code Online (Sandbox Code Playgroud)
但似乎Python无法做到这一点.这是真的?如果是这样,为什么?是否与类型无法修改的事实有关?
更新:我不想谈论猴子修补的不同定义,而是只关注上面的例子.我已经得出结论,由于你们中的一些人已经回答,所以无法做到.但我想更详细地解释为什么不能这样做,也许如果Python中有什么功能可以允许这样做.
回答你们中的一些人:我可能想要这样做的原因只是美学/可读性.
item.price.should_equal(19.99)
Run Code Online (Sandbox Code Playgroud)
这更像是英语,并清楚地表明哪个是测试值,哪个是预期值,如下所示:
should_equal(item.price, 19.99)
Run Code Online (Sandbox Code Playgroud)
这个概念就是Rspec和其他一些Ruby框架所基于的.
ruby python programming-languages fluent-interface monkeypatching
我想将一个方法添加到'list'类的单个实例中.例:
a = [1,2]
a.first = lambda self: return self[0]
Run Code Online (Sandbox Code Playgroud)
我知道这不起作用,但我希望像这样的东西.我知道这不是一个好习惯,我知道我应该做一个全新的课程,但我认为这在Python中是可行的,并且没有弄清楚如何.
我知道: 在Python中动态地将成员函数添加到类的实例中 并将 Python方法动态绑定到实例正确地绑定方法名称,但不是方法
但这些都不适用于原生列表.
谢谢!
我正在尝试重载字符串内置的一些方法.我知道没有真正合法的用例,但这种行为仍然让我感到烦恼,所以我想得到一个解释这里发生的事情:
使用Python2和forbiddenfruit
模块.
>>> from forbiddenfruit import curse
>>> curse(str, '__repr__', lambda self:'bar')
>>> 'foo'
'foo'
>>> 'foo'.__repr__()
'bar'
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,该__repr__
函数已成功重载,但在我们要求表示时实际上并未调用.这是为什么?
那么,你将如何做到预期的行为:
>>> 'foo'
'bar'
Run Code Online (Sandbox Code Playgroud)
没有关于设置自定义环境的限制,如果重建python是它所需要的,那就这样吧,但我真的不知道从哪里开始,我仍然希望有一个更简单的方法:)
假设我有3个python字符串,我可以格式化所有3个字符串,它们之间有2个分隔空格,如下所示:
h="hello"
m="my"
w="world"
print("{} {} {}".format(h,m,w))
Run Code Online (Sandbox Code Playgroud)
或使用
print("%s %s %s" % (h,m,w))
Run Code Online (Sandbox Code Playgroud)
现在假设我确定h和w都有值,但m可能是一个空字符串.上面的两个代码片段将导致"hello{two speces here}world
.
我知道我可以使用不同的函数和条件表达式来通过代码进行格式化
print(h+" " + m+(" " if len(m)>0 else "") + w)
Run Code Online (Sandbox Code Playgroud)
或选择不同的格式字符串
print(("{} {} {}" if len(m)>0 else "{}{} {}").format(h,m,w))
Run Code Online (Sandbox Code Playgroud)
基于m的长度.
我的问题是可以使用格式化字符串来完成吗?(例如,如果参数不为空,将填充1个空格的某些格式修饰符).
我有一个大型项目,在各个地方有问题的隐式Unicode转换(coersions)以例如:
someDynamicStr = "bar" # could come from various sources
# works
u"foo" + someDynamicStr
u"foo{}".format(someDynamicStr)
someDynamicStr = "\xff" # uh-oh
# raises UnicodeDecodeError
u"foo" + someDynamicStr
u"foo{}".format(someDynamicStr)
Run Code Online (Sandbox Code Playgroud)
(也可能是其他形式.)
现在我想跟踪这些用法,特别是那些积极使用的代码.
如果我可以轻松地unicode
用一个包装器替换构造函数会很好,它会检查输入是否为type str
并且encoding
/ errors
parameters设置为默认值然后通知我(打印回溯等).
/编辑:
虽然没有直接关系的东西我找我碰到了如何使解码异常干脆离开这个光荣可怕的黑客(解码一个唯一的,即str
到unicode
,而不是周围的其他方法,请参阅https://开头的邮件. python.org/pipermail/python-list/2012-July/627506.html).
我不打算使用它,但对于那些与无效的Unicode输入和寻找快速修复(但请考虑副作用)的问题进行斗争可能会很有趣:
import codecs
codecs.register_error("strict", codecs.ignore_errors)
codecs.register_error("strict", lambda x: (u"", x.end)) # alternatively
Run Code Online (Sandbox Code Playgroud)
(互联网搜索codecs.register_error("strict"
显示它显然用于某些真实项目.)
/编辑#2:
对于显式转换,我在monkeypatching的SO帖子的帮助下制作了一个片段:
class PatchedUnicode(unicode):
def __init__(self, obj=None, encoding=None, *args, **kwargs):
if encoding in (None, "ascii", …
Run Code Online (Sandbox Code Playgroud) 我想修补Python列表,特别是__setitem__
用自定义代码替换方法.请注意,我不是要扩展,而是覆盖内置类型.例如:
>>> # Monkey Patch
... # Replace list.__setitem__ with a Noop
...
>>> myList = [1,2,3,4,5]
>>> myList[0] = "Nope"
>>> myList
[1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)
是的,我知道这对python代码来说是一个彻头彻尾的变态.不,我的用例并没有多大意义.尽管如此,它能做到吗?
forbiddenfruit
模块允许修补C内置,但在尝试覆盖列表方法时不起作用我实际上设法覆盖了方法本身,如下所示:
import ctypes
def magic_get_dict(o):
# find address of dict whose offset is stored in the type
dict_addr = id(o) + type(o).__dictoffset__
# retrieve the dict object itself
dict_ptr …
Run Code Online (Sandbox Code Playgroud) 在Python中,我可以向C
先前定义的类添加属性。但是,我无法向其中添加属性list
-产生的错误消息说明这是因为list
是内置类型:
>>> class C: pass
...
>>> C.foo = 1
>>> C.foo
1
>>> list.foo = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'list'
Run Code Online (Sandbox Code Playgroud)
同样,可以将属性添加到的实例C
,但不能添加到的实例list
。但是,在这种情况下,错误消息更加模糊:
>>> o = C()
>>> o.bar = 2
>>> o.bar
2
>>> o = []
>>> o.bar = 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object …
Run Code Online (Sandbox Code Playgroud) Python似乎不允许您将属性分配给内部最高级别的"对象":
object.lst=lambda o:list(o)
Run Code Online (Sandbox Code Playgroud)
要么
func=lambda o:list(o)
setattr(object,'lst',func)
Run Code Online (Sandbox Code Playgroud)
全部生成错误消息.它背后的任何设计理由?老实说,这很奇怪,因为一切都是对象,你可以func(obj)
按照自己的意愿定义,所以如果func不是约束参数类型,为什么禁止添加方法呢?
obj.func()
如果你将func作为一个属性赋值给func(obj)object
.由于一切都是对象,因此对象的属性几乎是定义的全局函数.
无论如何要走动?
基本上如果你有能力为内置类型添加一些函数,你可以进行管道样式编程:obj.list().len().range()
我认为这种类型程序的可读性非常清晰,没有任何非pythonic.
python ×8
attributes ×1
ctypes ×1
debugging ×1
dynamic ×1
object ×1
oop ×1
overloading ×1
python-2.7 ×1
ruby ×1
unicode ×1