class Foo(object):
pass
foo = Foo()
def bar(self):
print 'bar'
Foo.bar = bar
foo.bar() #bar来自JavaScript,如果一个“类”原型增加了某个属性。已知该“类”的所有实例将在其原型链中具有该属性,因此不必对其任何实例或“子类”进行任何修改。
从这个意义上说,像Python这样的基于类的语言如何实现Monkey patching?
发布于 2011-06-09 06:37:49
真正的问题是,怎么可能不是呢?在Python中,类本身就是第一类对象。通过依次查找实例、类和父类上的属性(按方法解析顺序),可以解析对类实例的属性访问。这些查找都是在运行时完成的(就像Python中的一切一样)。如果在创建实例后向类添加属性,实例仍将“看到”新属性,原因很简单。
换句话说,它之所以有效,是因为Python不缓存属性(除非您的代码缓存),因为它不使用负缓存或影子类或任何会抑制它的优化技术(或者,当Python实现这样做时,它们会考虑到类可能会更改),并且因为一切都是运行时的。
发布于 2011-06-09 07:54:35
我刚刚通读了一大堆文档,据我所知,foo.bar是如何解决的,整个故事如下:
foo.__getattribute__吗?如果是,则使用foo.__getattribute__('bar')的结果。__getattribute__不会导致无限递归,但它的实现可能会。)__getattribute__,因为object中提供了默认实现-但该实现具有以下过程。;) )Foo中定义一个__getattribute__方法,并访问foo.__getattribute__,foo.__getattribute__('__getattribute__') 将被调用!但这并不意味着无限递归--如果你仔细的话;) )
__dict__,__class__,__bases__,__mro__)吗?如果是这样的话,就使用它。(据我所知,__getattribute__属于这一类,它避免了foo.__dict__字典中的无限recursion.)bar?如果是,使用foo.__dict__['bar'].foo.__mro__ exist (即,foo实际上是一个类)?如果是这样的话,为foo.__mro__1中的每个基类base执行foo.__mro__foo本身,我们已经在bar中使用了base.__dict__?如果是这样的话:x.__get__(foo, foo.__class__).x是我们发现的(再一次,递归地,但不会造成问题) x.__get__?base.__dict__['bar'].bar本身是一个对象,Python编译器会自动给函数一个__get__属性,这个属性被设计为在这个函数中使用
对于foo.__class__.__mro__的每个基类
foo.__class__.__mro__运行时提供”的情况。foo.__class__.__mro__[0]将始终为foo.__class__,即,在我们的example.)
foo.__mro__存在,我们也要这样做。这是因为类也有一个类:它的名称是type,它提供了最初用于计算__mro__属性的方法。)
bar in base.__dict__?如果是这样的话:x.__get__(foo, foo.__class__).
x是我们发现的(再一次,递归地,但不会造成问题) x.__get__?base.__dict__['bar'].bar本身是一个对象,Python编译器会自动给函数一个__get__属性,这个属性被设计为在这个函数中使用
foo.__getattr__吗?如果是,则使用foo.__getattr__('bar').raise AttributeError.的结果
bar.__get__并不是一个真正的函数--它是一个“方法包装器”--但你可以想象它是这样实现的:
# Somewhere in the Python internals
class __method_wrapper(object):
def __init__(self, func):
self.func = func
def __call__(self, obj, cls):
return lambda *args, **kwargs: func(obj, *args, **kwargs)
# Except it actually returns a "bound method" object
# that uses cls for its __repr__
# and there is a __repr__ for the method_wrapper that I *think*
# uses the hashcode of the underlying function, rather than of itself,
# but I'm not sure.
# Automatically done after compiling bar
bar.__get__ = __method_wrapper(bar)顺便说一句,在自动附加到bar的__get__中发生的“绑定”(称为描述符),或多或少就是您必须显式地为self方法指定Python参数的原因。在Javascript中,this本身是神奇的;在Python中,仅仅是将事物绑定到self的过程是神奇的。;)
是的,您可以在自己的对象上显式地设置一个方法,并在您将属性设置为对象的一个实例,然后从另一个类的实例访问它时,让它做一些特殊的事情。Python是极端的反射。:)但是,如果你想学习如何做到这一点,并真正全面地了解情况,你的have a lot阅读to do。;)
https://stackoverflow.com/questions/6286006
复制相似问题