2016-04-21 95 views
0

是显示我正在处理的API的继承的两个类。所以我希望基类ServiceTemplateTest为所有服务拥有一组共同的属性,使其表现得像OrderedDict对象一样。所以基类从OrderedDict入手。然后,我在__init__中执行super()以清除MRO问题。现在当我真正使用这个基类时,当我尝试从基类中分类__init()时,我遇到了问题。根据我的调试器,它说我需要调用:self._ServiceTemplateTest__init(),但是不应该因为我调用super()而只是__init()?什么是正确的方式让我继承而不必进行此调用:self._ServiceTemplateTest__init()使用super()(Python)时的继承问题

我是否需要在非基类上创建一个__init__(),我有多个super()调用?如果是这样,什么超级班应该先来?

感谢您提供任何建议!

from collections import OrderedDict 
import urllib2, json, urllib 
class ServiceTemplateTest(OrderedDict): 
    _con = None 
    _url = None 
    def __init__(self, url, connection=None, initialize=False, **kwargs): 
     super(ServiceTemplateTest, self).__init__() 
     self._url = url 
     self._con = connection 
     if initialize: 
      self.__init(connection) 
    def __init(self, connection=None): 
     if connection is None: 
      connection = self._con 
     attributes = [attr for attr in dir(self) 
         if not attr.startswith('__') and \ 
         not attr.startswith('_')] 
     params = {"f":"json"} 
     params = urllib.urlencode(params) 
     result = json.loads(
      urllib2.urlopen(url="{url}?{params}".format(url=self._url, 
                 params=params)).read()) 

     for k,v in result.items(): 
      if k in attributes: 
       setattr(self, "_"+ k, v) 
       self[k] = v 
      else: 
       self[k] = v 
     self.__dict__.update(result) 
    #---------------------------------------------------------------------- 
    @property 
    def connection(self): 
     return self._con 
    #---------------------------------------------------------------------- 
    @connection.setter 
    def connection(self, value): 
     self._con = value 
     self.refresh() 
    #---------------------------------------------------------------------- 
    @property 
    def url(self): 
     return self._url 
    #---------------------------------------------------------------------- 
    @url.setter 
    def url(self, value): 
     """""" 
     self._url = value 
     self.refresh() 
    #---------------------------------------------------------------------- 
    def __str__(self): 
     return json.dumps(self) 
    #---------------------------------------------------------------------- 
    def __repr__(self): 
     return self.__str__() 
    #---------------------------------------------------------------------- 
    def refresh(self): 
     self.__init() 

class SchematicService(ServiceTemplateTest): 
    """schematic service""" 
    _con = None 
    _json_dict = None 
    _json = None 
    _url = None 
    _nbSchematicLayers = None 
    _nbTemplates = None 
    _type = None 
    _name = None 
    _nbEstimatedDiagrams = None 
    def __init__(self, url, connection=None, initialize=False, **kwargs): 
     super(SchematicService, self).__init__(url=url, connection=connection, 
               initialize=initialize, **kwargs) 
     self._url = url 
     self._con = connection 
     if initialize: 
      self.__init(connection) 
    #---------------------------------------------------------------------- 
    @property 
    def nbSchematicLayers(self): 
     if self._nbSchematicLayers is None: 
      self.__init() 
     return self._nbSchematicLayers 
    #---------------------------------------------------------------------- 
    @property 
    def nbTemplates (self): 
     if self._nbTemplates is None: 
      self.__init() 
     return self._nbTemplates 
    #---------------------------------------------------------------------- 
    @property 
    def type(self): 
     if self._type is None: 
      self.__init() 
     return self._type 
    #---------------------------------------------------------------------- 
    @property 
    def name(self): 
     if self._name is None: 
      self.__init() 
     return self._name 
    #---------------------------------------------------------------------- 
    @property 
    def nbEstimatedDiagrams(self): 
     if self._nbEstimatedDiagrams is None: 
      self.__init() 
     return self._nbEstimatedDiagrams 
    @property 
    def somerandompropertytest(self): 
     return "hi" 
if __name__ == "__main__": 
    url = "http://servicesbeta6.esri.com/arcgis/rest/services/S1_Schematics/MapServer" 
    s = SchematicService(url=url, initialize=True) 
    print s 

回答

2

问题不在于继承或super(),但你试图从外部类所谓的“私人”的方法。任何名称以两个下划线开头的方法 - 在这种情况下您的__init() - 对于它们定义的类是私有的。

Python在您可能熟悉的方面并不真正具有“私有”其他面向对象语言,而不是它做一些叫做name mangling的东西,使它不方便,而不是不可能。从本质上讲,如果你命名一个像__init()这样的方法,Python会将它转换为名为_NameOfClass__init()的方法,并且在具有相同命名的调用(或访问属性)中也会这样做。诀窍是,“NameOfClass”部分始终是您访问方法的类的名称,从 - 子类SchematicService,就您的情况而言。由于名称不匹配,Python无法找到该方法。

当然,在Python中没有其他的东西真的是私人的。如果需要,可以通过自己改名来访问私有方法。然而,传统的看法通常不是使用双下划线私有方法或属性。按照惯例,如果你想在一个基类上有一个方法,这个方法不应该被从基类外部调用(例如,因为它不是你想支持的公共API的一部分),所以只需要命名一个方法领先的下划线。 Pythonistas知道这意味着,“这种方法或属性的签名,目的或存在可能会在以后消失,我不应该依赖它”。如果你打算将方法从任何地方调用 - 无论是在子类还是其他不相关的代码中 - 使它成为常规的公共方法(名称中没有前导下划线);如果您只希望它可以被子类访问,请使用单个前导下划线。

+0

谢谢,这是非常有帮助的。我总是学到新东西! –

+0

通过更改名称,像魅力一样工作。欣赏它。 –

1

dcrosta已经从一个子类中调用__init这个问题已经回答了(主要是我将要发布的相同的东西)。我只是想在你的代码示例中补充一点,整个SchematicService.__init__()只是没用,因为它只会重做ServiceTemplateTest.__init__()已经完成的工作。

此外,同时使类名和实例属性具有相同的名称不会有助于Wrt /可读性/可维护性。如果这些属性默认为尚未设置的实例属性,最好将它们设置为__init__()中的实例属性。

+0

你能举一个例子来解释你最后的陈述吗? –