Hay*_*don 9 python metaprogramming class
我希望使用元类来添加基于原始类的辅助方法.如果我希望添加的方法使用,self.__attributeName
我得到一个AttributeError
(因为名称修改)但是对于现有的相同方法,这不是问题.
这是一个简化的例子
# Function to be added as a method of Test
def newfunction2(self):
"""Function identical to newfunction"""
print self.mouse
print self._dog
print self.__cat
class MetaTest(type):
"""Metaclass to process the original class and
add new methods based on the original class
"""
def __new__(meta, name, base, dct):
newclass = super(MetaTest, meta).__new__(
meta, name, base, dct
)
# Condition for adding newfunction2
if "newfunction" in dct:
print "Found newfunction!"
print "Add newfunction2!"
setattr(newclass, "newfunction2", newfunction2)
return newclass
# Class to be modified by MetaTest
class Test(object):
__metaclass__ = MetaTest
def __init__(self):
self.__cat = "cat"
self._dog = "dog"
self.mouse = "mouse"
def newfunction(self):
"""Function identical to newfunction2"""
print self.mouse
print self._dog
print self.__cat
T = Test()
T.newfunction()
T.newfunction2() # AttributeError: 'Test' object has no attribute '__cat'
Run Code Online (Sandbox Code Playgroud)
有没有newfunction2
可以使用的添加方法self.__cat
?
(不重命名self.__cat
为self._cat
.)
也许更基本的东西,为什么不self.__cat
对这两种情况以同样的方式对待,因为newfunction2
现在是一部分Test
?
名称编译是在编译类中的方法时发生的。像这样的属性名称__foo
都被转换为_ClassName__foo
,其中,ClassName
是在其中定义该方法的类的名称。请注意,您可以对其他对象的属性使用名称修饰!
在您的代码中,mangling in名称newfunction2
不起作用,因为在编译函数时,该名称不属于该类。因此,对的查询__cat
不会变成__Test_cat
它们的处理方式Test.__init__
。您可以根据需要显式查找属性名称的变形版本,但这听起来像是newfunction2
通用的,并且可以添加到多个类中。不幸的是,这不适用于名称修饰。
确实,防止在类中未定义的代码访问属性是使用名称修饰的全部原因。通常,只有在编写代理或混合类型并且不希望内部使用属性与您要代理或混合的类的属性相冲突时,才值得打扰(您不会知道提前)。