Python 在父函数中使用由子函数重写的值

Python 在父函数中使用由子函数重写的值,python,python-3.x,class,Python,Python 3.x,Class,我定义了一个基类来处理泛型内容,以及子类,它们更具体地接受哪些内容(对象类型)。但是,在调用父类中定义的函数时,将使用父变量而不是子变量。如何让Python在父函数中使用子变量 示例代码: class BaseField(object): __accepted_types = (object,) def __init__(self, description=""): self.content = None self.description = d

我定义了一个基类来处理泛型内容,以及子类,它们更具体地接受哪些内容(对象类型)。但是,在调用父类中定义的函数时,将使用父变量而不是子变量。如何让Python在父函数中使用子变量

示例代码:

class BaseField(object):
    __accepted_types = (object,)

    def __init__(self, description=""):
        self.content = None
        self.description = description

    def set(self, content):
        if isinstance(content, self.__accepted_types):
            print(type(content), self.__accepted_types)
            print(type(self))
            self.__set(content)
        else:
            raise ValueError("wrong type")

    def __set(self, content):
        pass

class StringField(BaseField):
    __accepted_types = (basestring,)

    def __init__(self, description=""):
        super().__init__(description)
        print(self.__accepted_types)

if __name__ == '__main__':
    x = StringField("a test field")
    x.set(3)
我希望这段代码会引发一个
ValueError
(我试图将
int
传递给一个只接受
str
的类),但是我得到了以下结果:

(<class 'str'>,)
<class 'int'> (<class 'object'>,) <class '__main__.StringField'>
(,)
(,) 

请注意,该函数正确地返回它在
“StringField”
中,但使用
“BaseField”
值作为
\uu接受的类型。如果我将
\u accepted\u types
声明为实例变量,则行为是相同的。

您是name mangling的受害者;名称在类主体和
self中被损坏。接受的\u类型
get被转换为
\u基本字段\u接受的\u类型
内部
set

将所有出现的
\u accepted\u types
更改为
accepted\u types
,它就可以正常工作了


p、 s如果您确实在使用Python 3,
basestring
不存在,请使用
str

作为另一个答案的后续,我强烈建议您观看PyCon 2013,其中讨论了Python名称混乱范例的目的和用法

总而言之,对对象变量使用双下划线并不是保持它们“私有”的方法。事实上,Python中的私有变量不是“一件事”;当来自其他语言时,有效地使用Python需要在这个和其他主题上转变思维

名称混乱的目的是防止父类和子类落入命名空间战争的陷阱,例如,在命名空间战争中,某些子类使用属性名的目的与父类不同

如需进一步阅读,请参阅以下其他问题和答案:


你能说得更具体些吗?当在
set(self,content)
方法中将
self.\uu accepted\u types
更改为
\uuuu accepted\u types
accepted\u types
时,我得到
名称错误:没有定义名称“\u BaseField\uu accepted\u types”
只需在任何地方删除接受的类型的“\uu”前缀。是的,正如jsbueno所指出的,将
\uuu accepted\u types
更改为
accepted\u types
。您陷入的陷阱是:您可能来自一种属性可以被“保护”和“特权”的语言—Python不是这样工作的。它有一个名称篡改机制,可以让基类准确地看到它定义的属性的非overiden版本-属性的“\uuuuu”前缀。你想要的东西的位置。事实上,早期的Python教程错误地将这种机制与某种形式的“受保护”属性访问相混淆,而事实并非如此。谢谢,这就解决了问题(同时也感谢在Python3中使用的
/
str
)。正如jsbueno所提到的,我假设_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。。。