使用super()时的继承问题(Python)
下面是两个类,它们显示了我正在处理的API的继承。因此,我希望基类ServiceTemplateTest为所有服务和提供一组公共属性,使其行为类似于OrderedDict对象。因此,基类继承自OrderedDict。然后,我在使用super()时的继承问题(Python),python,python-2.7,super,Python,Python 2.7,Super,下面是两个类,它们显示了我正在处理的API的继承。因此,我希望基类ServiceTemplateTest为所有服务和提供一组公共属性,使其行为类似于OrderedDict对象。因此,基类继承自OrderedDict。然后,我在\uuu init\uuu中执行super(),以清除MRO问题。现在,当我实际使用这个基类时,当我尝试从基类中初始化\uu init()时,会遇到问题。根据我的调试器,它说我需要调用:self.\u ServiceTemplateTest\u_init(),但既然我调用s
\uuu init\uuu
中执行super()
,以清除MRO问题。现在,当我实际使用这个基类时,当我尝试从基类中初始化\uu init()
时,会遇到问题。根据我的调试器,它说我需要调用:self.\u ServiceTemplateTest\u_init()
,但既然我调用super(),它不应该是\u_init()
?允许我继承而不必执行此调用的正确方法是什么:self.\u servicemplatetest\u init()
我是否需要在有多个super()调用的非基类上创建一个\uuu init\uu()
?如果是这样的话,什么超级类应该排在第一位
感谢您提供的任何建议
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
问题不是继承或
super()
,而是您试图从类外部调用“private”方法。任何名称以两个下划线开头的方法——在本例中是您的\uu init()
——都是它们在其中定义的类的私有方法
Python并没有真正的“private”,您可能会从其他OO语言中熟悉它,相反,它做了一些调用,使它变得不方便,而不是不可能。本质上,如果您将一个方法命名为\uu init()
,Python将把它转换为一个名为\u NameOfClass\uu init()
的方法,并在具有类似命名的调用(或访问属性)中执行相同的操作。诀窍是,“NameOfClass”部分始终是访问方法的类的名称——在您的例子中是子类,schematicsservice
。由于名称不匹配,Python无法找到该方法
当然,在Python中,实际上没有什么是真正私有的。如果需要,您可以通过修改私有方法的名称来访问它。然而,传统智慧通常是根本不使用双下划线私有方法或属性。按照惯例,如果您希望在基类上有一个不打算从基类外部调用的方法(例如,因为它不是您想要支持的公共API的一部分),请使用一个前导下划线将其命名。Pythonistas知道这意味着,“这个方法或属性的签名、目的,甚至存在可能在以后的某个日期消失,我不应该依赖它”
My$0.02:如果您希望该方法可以从任何地方调用(包括在子类和其他无关代码中),请将其设置为常规公共方法(名称中没有前导下划线);如果您只希望子类可以访问它,请使用一个前导下划线。问题不是继承或
super()
,而是您试图从类外部调用“private”方法。任何名称以两个下划线开头的方法——在本例中是您的\uu init()
——都是它们在其中定义的类的私有方法
Python并没有真正的“private”,您可能会从其他OO语言中熟悉它,相反,它做了一些调用,使它变得不方便,而不是不可能。本质上,如果您将一个方法命名为\uu init()
,Python将把它转换为一个名为\u NameOfClass\uu init()
的方法,并在具有类似命名的调用(或访问属性)中执行相同的操作。诀窍是,“NameOfClass”部分始终是访问方法的类的名称——在您的例子中是子类,schematicsservice
。由于名称不匹配,Python无法找到该方法
当然,在Python中,实际上没有什么是真正私有的。如果需要,您可以通过修改私有方法的名称来访问它。然而,传统智慧通常是根本不使用双下划线私有方法或属性。按照惯例,如果您希望在基类上有一个不打算从基类外部调用的方法(例如,因为它不是您想要支持的公共API的一部分),请使用一个前导下划线将其命名。Pythonistas知道这意味着,“这个方法或属性的签名、目的,甚至存在可能在以后的某个日期消失,我不应该依赖它”
My$0.02:如果您希望该方法可以从任何地方调用(包括在子类和其他无关代码中),请将其设置为常规公共方法(名称中没有前导下划线);如果您只希望子类可以访问它,请使用一个前导下划线。dcrosta已经回答了从子类调用\u init
的问题(主要与我将要发布的内容相同)。我只想在您的代码示例中添加这一点,整个schematicsservice.\uuu init\uu()
都是无用的,因为它只会重复ServiceTemplateTest.\uu init\uu()
已经完成的操作
同样,使用相同名称的类属性和实例属性也无助于wrt/可读性/可维护性。如果这些是尚未设置的实例属性的默认值,那么最好将它们设置为\uuuu init\uuuu()
dcrosta已经回答了(主要与我即将发布的内容相同)从子类调用\uu init
的问题。我只想在您的代码示例中添加这一点,整个schematicsservice.\uuu init\uu()
都是无用的,因为它只会重复ServiceTemplateTest.\uu init\uu()
已经完成的操作
同样,使用相同名称的类属性和实例属性也无助于wrt/可读性/可维护性。如果这些属性是尚未设置的实例属性的默认值,那么最好在\uuu init\uuuu()
中将它们设置为实例属性。谢谢,这是ve