什么是正确的代码方法,例如,Weather
类,它解析4个不同的来源?这是我如何做到的:
创建了一个名为Weather
的类,其中包含4个属性(例如temp
,windspeed
,pressure
,humidity
)和4个方法,例如{{1 },...,parse_source1
。为了获得结果,我创建了4个对象,并在每个对象上调用不同的方法。
但是现在我很困惑,如果这是解决这个问题的正确方法。也许我应该创建具有所有属性的parse_source4
类,然后使用继承并将解析放入Weather
?
答案 0 :(得分:2)
我不确定这是一个适当的问题,因为可能有太多“正确”的方法,但无论如何,这是一个我发现太多次的问题,同样的解决方案总是起作用我,用各种语言。
我会说每个对象都有一个解析器类会更好:
class JSONWeatherParser(object):
def parse(self, value):
json_obj = json.load(value)
w = Weather()
# Do some stuff here, assign values from json_obj to w etc.
return w
class XMLWeatherParser(object):
def parse(self, value):
element = xml.etree.ElementTree(value)
w = Weather()
# Do some stuff here, assign values from element to w etc.
return w
class YAMLWeatherParser(object):
def parse(self, value):
w = Weather()
# Sorry, I do not even know what it looks like
return w
将课程放在字典上也很酷:
weather_parsers = {
'xml': XMLWeatherParser,
'json': JSONWeatherParser,
'yaml': YAMLWeatherParser
}
现在你可以做到:
format = request.get('format') # For example
data = request.get('weather')
parser = weather_parsers[format]()
weather = parser.parse(data)
事实上,在Python中你甚至不需要这些*WeatherParser
类:你可以创建*_weather_parser
函数,这会更简单:
def json_weather_parse(value):
json_obj = json.load(value)
w = Weather()
# Do some stuff here, assign values from json_obj to w etc.
return w
def xml_weather_parse(value):
element = xml.etree.ElementTree(value)
w = Weather()
# Do some stuff here, assign values from element to w etc.
return w
def yaml_weather_parse(value):
w = Weather()
# Sorry, I do not even know what it looks like
return w
如果你的解析器只做和的解析器并不保留状态,那么函数是一个更好的选择。 OTOH的类方法更通用,语言无关且功能强大。关键是,你可能不需要那么大的力量。
总结:虽然从理论上讲,为每种行为制作不同的Weather
课程会很酷(所有孩子都在这样做! - 或者他们在90年代都是这样做的)实践中,将解析问题与模型分开似乎更易于管理。
编辑:HannesOvrén提出了一个很好的问题。
实际上,解析器类更复杂,我宁愿使用解析器函数。现在,为什么不制作Weather
方法呢?好吧,解析一些特定的类'实例并不像这个类所期望的行为那样,所以看起来更好的范围是将这个问题放在不同的地方。当然,我们不会指望一个不存在的实例来解析它自己!
当然,我们可以将它放在类方法上,就像在Django等人中完成的那样,但为什么要创建一个方法,如果一个函数会这样做?在这种情况下,它与风格更相关,我在these old school rules;)
播放更重要的是,这在某种意义上是一种风格问题,我的方法将是所描述的。但是,我知道这只是一种方法,还有许多其他方法与此方法一样有用且“正确”。我不认为类方法是错误的,但我也不会使用它们。
答案 1 :(得分:1)
最好将Weather
类与解析代码分开,即
class Weather:
def __init__(...):
...
def parse_weather(source):
if source == ...:
...
return Weather(...)
这样,添加或删除源时,您的类不必更改。你甚至可以创建一个单独的类;
class WeatherParser:
def __init__(source):
...
def parse_weather(...):
...
return Weather(...)
哪个包含你的解析方法
答案 2 :(得分:1)
如果您是该类的唯一实现者,我将使用@classmethod
装饰器来创建工厂函数。这样,解析器/源很容易找到,因为它们是Weather
类的一部分。
class Weather(object):
def __init__(self, temp, windspeed, humidity, pressure):
# Initialize everything ...
@classmethod
def from_source1(cls, source1):
# Parse source 1, get temp, windspeed, humidity and pressure
# ...
instance = cls(temp, windspeed, humidity, pressure)
return instance
weather = Weather.from_source1(source1)
如果您希望其他人使用您的课程,并且可能想要实施他们自己的资源,那么我认为您有两个不错的选择:
在__init__
中进行解析并让用户对您的Weather
基类进行子类化。
创建一个WeatherParser
基类,让用户继承该基类。
我认为第一个选项更直观,因为您避免创建更多类。 最重要的是(在我看来),对于添加新资源的正确方法毫无疑问。