是否真的“然而,当首次定义类时,这组方法是固定的”?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否真的“然而,当首次定义类时,这组方法是固定的”?相关的知识,希望对你有一定的参考价值。
来自Programming Language Pragmatics, by Scott
对于类的内容(成员),Python和Ruby都比php或更传统的面向对象语言更灵活。只需分配给Python对象,就可以将新字段添加到Python对象中:my_object.new_field = value。但是,在首次定义类时,这组方法是固定的。在Ruby中,只有方法在类外可见(“put”和“get”方法必须用于访问字段),并且必须显式声明所有方法。但是,可以修改现有的类声明,添加或覆盖方法。甚至可以在逐个对象的基础上执行此操作。因此,同一类的两个对象可能不会显示相同的行为。
然而,“当首次定义类时,这组方法是否已修复”是什么意思?
我似乎找到了一个反例:
>>> class E:
... pass
...
>>> E.__dict__
mappingproxy({'__module__': '__main__', '__dict__': <attribute '__dict__' of 'E' objects>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'E' objects>})
>>> def myfun():
... pass
...
>>> E.mf=myfun
>>> E.__dict__
mappingproxy({'__module__': '__main__', '__dict__': <attribute '__dict__' of 'E' objects>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'E' objects>, 'mf': <function myfun at 0x7f6561daba60>})
就像问题中所示:向类对象添加一个函数是很简单的,它的行为就像任何方法一样:
def fake_method(self,idx):
print(self, idx)
class MyClass(object):
pass
MyClass.new_method = fake_method
n = MyClass()
n.new_method(10)
# <__main__.MyClass object at 0x000001BBA6E90860> 10
您还可以向实例添加“类似方法”的“可调用属性”:
import types
def fake_method(self,idx):
print(self, idx)
class MyClass(object):
pass
n = MyClass()
n.new_method = types.MethodType(fake_method, n)
n.new_method(10)
# <__main__.MyClass object at 0x000001BBA6E9C2E8> 10
这里需要types.MethodType
,因为否则它会表现得像staticmethod
。
我的总结:要么我错过了引用的一些关键点,要么是错的。
在实例级别,可以直接修改字段,如上所述。
在类/模块级别,有一个名为monkey patching
的非官方机制。基本上,您将获得类/模块的引用(?),并覆盖该函数。
但是,我不清楚是否可以覆盖静态方法。并且修改仅在完成猴子补丁的本地范围内有效,我相信。因此,您不应期望导入相同类/模块的其他脚本共享Monkey补丁,除非它们也明确应用补丁。当然,您也可以创建一个包装器模块。
我不认为这是Python社区提倡的。很长一段时间内很难将补丁保持在轨道上。
以上是关于是否真的“然而,当首次定义类时,这组方法是固定的”?的主要内容,如果未能解决你的问题,请参考以下文章