Python类方法,何时返回self? [英] Python class methods, when to return self?

查看:400
本文介绍了Python类方法,何时返回self?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于何时在类内返回self以及何时返回可能用于检查方法是否正确运行的值,我感到困惑.

I'm confused as to when to return self inside a class and when to return a value which may or may not possibly be used to check the method ran correctly.

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我应该返回什么?

So above theres a few examples. api_request I know having the text response is a must. But with send_message what should I return?

,然后将其转换为字典以检查键是否存在,否则引发错误).

which is then converted to a dict to check a key exists, else raise error).

它应该返回True,response-> dict还是self?

Should it return True, the response->dict, or self?

预先感谢

推荐答案

由于错误通常是作为异常传递的,因此成功/失败返回值很少有用,因此许多对象修饰符函数最终都没有返回值全部-更确切地说,返回None,因为您根本无法返回任何内容. (考虑一些Python的内置对象,例如list,其中appendextend返回None,以及dict,其中dict.update返回None.)

Since errors tend to be delivered as exceptions and hence success/fail return values are rarely useful, a lot of object-modifier functions wind up with no return value at all—or more precisely, return None, since you can't return nothing-at-all. (Consider some of Python's built-in objects, like list, where append and extend return None, and dict, where dict.update returns None.)

尽管如此,即使某些Pythonista用户不喜欢,返回self对于链接方法调用也很方便.请参阅应该内部类方法返回值还是只是在python中修改实例变量?.

Still, returning self is convenient for chaining method calls, even if some Pythonistas don't like it. See kindall's answer in Should internal class methods returnvalues or just modify instance variables in python? for example.

编辑以基于注释添加一些示例:

Edit to add some examples based on comment:

您应该"返回的结果(或引发异常,在这种情况下为什么异常")取决于问题.您是否要send_message()等待响应,验证该响应,并验证其是否良好?如果是这样,您是否希望它在没有响应,验证失败或响应有效但显示消息已拒绝"的情况下引发错误?如果是这样,您是否希望每次失败都出现不同错误,等等?一种合理(对于合理值而言)的方法是捕获所有具有基本"异常的故障,并将每种类型"故障作为该故障的衍生:

What you "should" return—or raise an exception, in which case, "what exception"—depends on the problem. Do you want send_message() to wait for a response, validate that response, and verify that it was good? If so, do you want it to raise an error if there is no response, the validation fails, or the response was valid but says "message rejected"? If so, do you want different errors for each failure, etc? One reasonable (for some value of reasonable) method is to capture all failures with a "base" exception, and make each "type" of failure a derivative of that:

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

现在您的某些功能可能看起来像这样(请注意,这些功能均未经过测试):

Now some of your functions might look something like this (note, none of this is tested):

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)

然后您需要一些内部"功能,如下所示:

Then you need some "internal" functions like these:

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,并且不会遇到您自己的所有错误;例如,也许您可​​以将错误压缩到ValueErrorKeyError等.

You might choose not to translate socket.errors at all, and not have all your own errors; perhaps you can squeeze your errors into ValueError and KeyError and so on, for instance.

这些选择就是编程的全部内容!

These choices are what programming is all about!

这篇关于Python类方法,何时返回self?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆