我对何时在类中返回self以及何时返回一个可能用于或可能不用于检查方法是否正确运行的值感到困惑。
def api_request(self, data):
#api web request code
return response.text
def connect(self):
#login to api, set some vars defined in __init__
return self
def send_message(self, message):
#send msg code
return self
所以上面有几个例子。api_request我知道文本回复是必须的。但是对于send_message,我应该返回什么呢?
然后将其转换为dict以检查密钥是否存在,否则引发错误)。
它应该返回True、response->dict还是self?
提前感谢
发布于 2013-07-04 08:10:13
由于错误倾向于作为异常传递,因此成功/失败返回值很少有用,因此许多对象修饰符函数最终根本没有返回值-或者更准确地说,返回None
,因为您根本不能返回任何东西。(考虑一些Python的内置对象,比如list
,其中append
和extend
返回None
,以及dict
,其中dict.update
返回None
。)
不过,返回self
对于链接方法调用还是很方便的,即使有些Pythonistas不喜欢这样做。例如,请参阅Should internal class methods returnvalues or just modify instance variables in python?中的金德尔答案。
编辑以添加一些基于注释的示例:
你“应该”返回什么-或者引发一个异常,在这种情况下,“什么异常”在问题上-depends。是否希望send_message()
等待响应、验证该响应并验证其是否正常?如果是这样,您是否希望在没有响应、验证失败或响应有效但显示"message rejected“的情况下引发错误?如果是这样,您是否希望每个失败都有不同的错误,等等?一种合理的(对于某些合理的值)方法是用“基本”异常捕获所有故障,并使每种“类型”的故障都是该异常的派生:
class ZorgError(Exception): # catch-all "can't talk via the Zorg-brand XML API"
pass
class ZorgRemoteDown(ZorgError): # connect or send failed, or no response/timeout
pass
class ZorgNuts(ZorgError): # remote response incomprehensible
pass
class ZorgDenied(ZorgError): # remote says "permission denied"
pass
# add more if needed
现在,您的一些函数可能如下所示(请注意,这些函数都没有经过测试):
def connect(self):
"""connect to server, log in"""
... # do some prep work
addr = self._addr
try:
self._sock.connect(addr)
except socket.error as err:
if err.errno == errno.ECONNREFUSED: # server is down
raise ZorgRemoteDown(addr) # translate that to our Zorg error
# add more special translation here if needed
raise # some other problem, propagate it
... # do other stuff now that we're connected, including trying to log in
response = self._get_response()
if response == 'login denied' # or whatever that looks like
raise ZorgDenied() # maybe say what exactly was denied, maybe not
# all went well, return None by not returning anything
def send_message(self, msg):
"""encode the message in the way the remote likes, send it, and wait for
a response from the remote."""
response = self._send_and_wait(self._encode(msg))
if response == 'ok':
return
if response == 'permission denied':
raise ZorgDenied()
# don't understand what we got back, so say the remote is crazy
raise ZorgNuts(response)
然后你需要一些像这样的“内部”函数:
def _send_and_wait(self, raw_xml):
"""send raw XML to server"""
try:
self._sock.sendall(raw_xml)
except socket.error as err:
if err.errno in (errno.EHOSTDOWN, errno.ENETDOWN) # add more if needed
raise ZorgRemoteDown(self._addr)
raise
return self._get_response()
def _get_response(self):
"""wait for a response, which is supposedly XML-encoded"""
... some code here ...
if we_got_a_timeout_while_waiting:
raise ZorgRemoteDown(self._addr)
try:
return some_xml_decoding_stuff(raw_xml)
except SomeXMLDecodeError:
raise ZorgNuts(raw_xml) # or something else suitable for debug
您可能选择根本不翻译socket.error
,也不会有自己的所有错误;例如,您可以将错误压缩到ValueError
和KeyError
中,依此类推。
这些选择就是编程的全部内容!
发布于 2013-07-04 08:02:05
通常,python中的对象是可变的。因此,您不会返回self
,因为您在方法中所做的修改会反映在对象本身中。
使用您的示例:
api = API() # initialise the API
if api.connect(): # perhaps return a bool, indicating that the connection succeeded
api.send_message() # you now know that this API instance is connected, and can send messages
https://stackoverflow.com/questions/17459970
复制相似问题