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