使用父函数中的子项覆盖值

时间:2017-05-02 14:53:13

标签: python python-3.x class

我已经定义了一个处理泛型内容的基类,以及它们接受的内容(对象类型)更具体的子类。但是,在调用父类中定义的函数时,将使用父变量而不是子变量。如何让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"的{​​{1}}值。如果我将__accepted_types声明为实例变量,则行为相同。

2 个答案:

答案 0 :(得分:2)

你正在成为名字破坏的受害者;这些名称在类体内被破坏,self.__accepted_types被转换为_BaseField__accepted_types内的set

将所有__accepted_types更改为accepted_types,它会正常工作。

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

答案 1 :(得分:1)

作为另一个答案的后续内容,我强烈建议您从PyCon 2013中观看this talk,其中讨论了Python名称修改范例的目的和用途。

总而言之,对你的对象变量使用双下划线不是保持它们的一种方式&#34; private&#34;。事实上,Python中的私有变量不是&#34;事情&#34 ;;当来自其他语言时,有效地使用Python需要转变思考这个和其他主题。

名称的目的 - 修改它以防止父类和子类陷入命名空间战争的陷阱,例如,某些子类使用属性名称的目的与父类不同。

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

Underscore vs Double underscore with variables and methods

What is the meaning of a single- and a double-underscore before an object name?