Python “如何访问”__&引用;(双下划线)添加到类的方法中的变量 背景
我希望使用一个元类,以便在原始类的基础上添加助手方法。如果我想添加的方法使用了Python “如何访问”__&引用;(双下划线)添加到类的方法中的变量 背景,python,class,metaprogramming,Python,Class,Metaprogramming,我希望使用一个元类,以便在原始类的基础上添加助手方法。如果我想添加的方法使用了self.\uu attributeName我会得到一个AttributeError(因为名称混乱),但对于现有的相同方法,这不是问题 代码示例 下面是一个简化的例子 # Function to be added as a method of Test def newfunction2(self): """Function identical to newfunction""" print self.m
self.\uu 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'
问题:
是否有一种添加newfunction2
的方法可以使用self.\uu cat
(无需将self.\uu cat
重命名为self.\u cat
)
也许还有更基本的问题,为什么这两种情况下,self.\uu cat
的处理方式不一样,因为newfunction2
现在是Test
的一部分?您可以使用\u Test\uu cat
从Test
类访问\uu cat
属性。(其中,
替换为self
或测试
类的任何其他实例)
在中了解更多信息以回答您的两个问题:
newfunction2
调用为self.\u Test\u cat
时,您需要将其更改为self.\u cat
,这要归功于名称损坏规则李>
让我帮你把它打断,意思是当你的解释器遇到一个被弄坏的名字时,它在哪里阅读并不重要仅当名称出现在类的定义中时,名称才会被损坏,而在您的情况下,它不是。因为它不是直接“在”类定义之下。因此,当它读取
self.\uuuuu cat
时,它将其保持在self.\uuu cat
,不会将其文本替换为self.\utest\uu cat
,因为它不是在Test
类中定义的。编译类中的方法时会发生名称损坏。像\uuuuufoo
这样的属性名会被转入\u ClassName\uuuuuufoo
,其中ClassName
是定义方法的类的名称。请注意,您可以对其他对象的属性使用名称混乱
在您的代码中,newfunction2
中的名称不起作用,因为编译函数时,它不是类的一部分。因此,\uuuuuCAT
的查找不会像在测试中那样变成\uuuuTEST\uCAT
。如果愿意,您可以显式查找属性名称的损坏版本,但听起来您希望newfunction2
是泛型的,并且可以添加到多个类中。不幸的是,这不适用于名称损坏
实际上,防止类中未定义的代码访问属性是使用名称篡改的全部原因。通常,只有在编写代理或mixin类型并且不希望内部使用属性与代理或混合的类的属性发生冲突(您事先不知道)的情况下,才值得考虑这个问题。我想到了这一点,但由于我将newmethod2
添加为一个方法,我认为行为应该是一样的。i、 e.我可以访问的self.\uu cat
。相关:Django的本文档教程中可能存在的副本。代码行'Question.objects.get(pub_date_year=current_year')和pub date year变量有一个双下划线,这与您提到的相同吗@Blckknght@LordDraagon:不,那似乎是Django自己的事。它的拼写可能部分受到Python的本地名称mangling的启发,但它是单独实现的,具有不同的含义。我认为双下划线有点像属性符号中的点(因此pub\u date\u year
有点像pub\u date.year
)。我对Django了解不够,无法给出更完整的解释。请您补充一些解释,解释为什么这可以解决原始海报的问题。
class B:
def __init__(self):
self.__private = 0
def __private_method(self):
'''A private method via inheritance'''
return ('{!r}'.format(self))
def internal_method(self):
return ('{!s}'.format(self))
class C(B):
def __init__(self):
super().__init__()
self.__private = 1
def __private_method(self):
return 'Am from class C'
c = C()
print(c.__dict__)
b = B()
print(b.__dict__)
print(b._B__private)
print(c._C__private_method())