添加到类的方法中的变量

添加到类的方法中的变量

本文介绍了如何访问“__"(双下划线)添加到类的方法中的变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我希望使用元类来添加基于原始类的辅助方法.如果我想添加的方法使用 self.__attributeName 我得到一个 AttributeError(因为名称修改)但对于现有的相同方法这不是问题.>

代码示例

这是一个简化的例子

# 作为Test方法添加的函数def newfunction2(self):"""与newfunction相同的功能"""打印 self.mouse打印 self._dog打印 self.__cat类元测试(类型):"""元类处理原始类和在原始类的基础上添加新方法"""def __new__(meta, name, base, dct):newclass = super(MetaTest, meta).__new__(元、名称、基数、dct)# 添加newfunction2的条件如果 dct 中的新函数":打印发现新功能!"打印添加新功能2!"setattr(newclass, "newfunction2", newfunction2)返回新班级# MetaTest 要修改的类类测试(对象):__元类__ = 元测试def __init__(self):self.__cat = "猫"self._dog = "狗"self.mouse = "鼠标"def newfunction(self):"""功能与 newfunction2 相同"""打印 self.mouse打印 self._dog打印 self.__catT = 测试()T.newfunction()T.newfunction2() # AttributeError: 'Test' 对象没有属性 '__cat'

问题

有没有办法添加可以使用self.__catnewfunction2?

(无需将 self.__cat 重命名为 self._cat.)

也许还有一些更基本的东西,为什么 self.__cat 在这两种情况下不以相同的方式处理,因为 newfunction2 现在是 Test?

解决方案

在编译类中的方法时会发生名称修改.__foo 之类的属性名称被转换为 _ClassName__foo,其中 ClassName 是定义方法的类的名称.请注意,您可以使用其他对象属性的名称修改!

在您的代码中,newfunction2 中的名称修改不起作用,因为在编译函数时,它不是类的一部分.因此,__cat 的查找不会像在 Test.__init__ 中那样变成 __Test_cat.如果需要,您可以显式查找属性名称的损坏版本,但听起来您希望 newfunction2 是通用的,并且能够添加到多个类中.不幸的是,这不适用于名称修改.

确实,防止类中未定义的代码访问您的属性是使用名称修改的全部原因.通常,如果您正在编写代理或混合类型并且您不希望您的内部使用属性与您正在代理或混合的类的属性发生冲突(您不会知道)提前).

Background

I wish to use a meta class in order to add helper methods based on the original class. If the method I wish to add uses self.__attributeName I get an AttributeError (because of name mangling) but for an existing identical method this isn't a problem.

Code example

Here is a simplified example

# 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'

Question

Is there a way of adding newfunction2 that could use self.__cat?

(Without renaming self.__cat to self._cat.)

And maybe something more fundamental, why isn't self.__cat being treated in the same way for both cases since newfunction2 is now part of Test?

解决方案

Name mangling happens when the methods in a class are compiled. Attribute names like __foo are turned in to _ClassName__foo, where ClassName is the name of the class the method is defined in. Note that you can use name mangling for attributes of other objects!

In your code, the name mangling in newfunction2 doesn't work because when the function is compiled, it's not part of the class. Thus the lookups of __cat don't get turned into __Test_cat the way they did in Test.__init__. You could explicitly look up the mangled version of the attribute name if you want, but it sounds like you want newfunction2 to be generic, and able to be added to multiple classes. Unfortunately, that doesn't work with name mangling.

Indeed, preventing code not defined in your class from accessing your attributes is the whole reason to use name mangling. Usually it's only worth bothering with if you're writing a proxy or mixin type and you don't want your internal-use attributes to collide with the attributes of the class you're proxying or mixing in with (which you won't know in advance).

这篇关于如何访问“__"(双下划线)添加到类的方法中的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 06:34