Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 我应该如何重构一段存在于许多不同函数中但包含return语句的代码_Python_Django_Refactoring - Fatal编程技术网

Python 我应该如何重构一段存在于许多不同函数中但包含return语句的代码

Python 我应该如何重构一段存在于许多不同函数中但包含return语句的代码,python,django,refactoring,Python,Django,Refactoring,代码片段来自django视图代码,但这并不重要 假设我有下面的一段代码 def unsubscribe(request): #start of block user = request.user sid = request.POST.get('subscription_id') try: sub = Subscription.objects.get(id=sid) except ObjectDoesNotExist: return ajax_response(

代码片段来自django视图代码,但这并不重要

假设我有下面的一段代码

def unsubscribe(request):
  #start of block
  user = request.user
  sid = request.POST.get('subscription_id')
  try:
    sub = Subscription.objects.get(id=sid)
  except ObjectDoesNotExist:
    return ajax_response(False, [('subscription', 'Given subscription does not exist.')])
  if sub.user != user:
    return ajax_response(False, [('subscription', 'Invalid permission.')])
  #end of block.
  sub.is_active = False
  sub.save()
  return ajax_response(True)
比如说,我有另一个函数
resubscribe()
,它的作用与上述函数完全相同,只是它的作用是
sub.is\u active=True

在这种情况下,组织代码的最佳方式是什么,这样
#block
#endblock
之间的代码就不会重复?我想一般来说,这个问题可以写成:

有一段代码可以复制并粘贴到许多不同的函数上。但是,这段代码包含
return
语句。在这种情况下,将这段逻辑抽象出来的最佳方法是什么

编辑:修复了代码段

EDIT2:实际上,解决这个问题的简单方法是创建一个函数,比如toggle_active_status,它接受
request
和一个布尔值。(我把问题贴出来后就明白了)


但是,我想知道函数之间的不同逻辑超过1行的情况。。。比如说,在#block和#endlbock之间的代码只进行输入验证,可能会出现任意应用程序逻辑

一种方法是简单地创建一个包含重复功能的单独函数。您可以使用函数的参数来引入必要的差异


如果代码段返回某些内容,则可以使用约定,例如如果函数不应返回,则返回
None
,否则返回对象。在调用者函数中,只需测试返回的参数是否为
None
,如果返回的变量不是
None

,则返回该变量。一种方法是简单地创建一个包含重复功能的单独函数。您可以使用函数的参数来引入必要的差异


如果代码段返回某些内容,则可以使用约定,例如如果函数不应返回,则返回
None
,否则返回对象。在调用者函数中,只需测试返回的参数是否为
None
,如果返回的变量不是
None
,则返回该变量,将重复的块分解出来,并将差异传递进来,创建传递差异的包装函数:

def alter_subscription(request, make_active):
  # start of block
  # (...)
  # end of block
  sub.is_active = make_active
  sub.save()
  return ajax_response(True)

def unsubscribe(request):
  return alter_subscription(request, False)

def resubscribe(request):
  return alter_subscription(request, True)

分解出重复的块并传入差异,创建传入差异的包装函数:

def alter_subscription(request, make_active):
  # start of block
  # (...)
  # end of block
  sub.is_active = make_active
  sub.save()
  return ajax_response(True)

def unsubscribe(request):
  return alter_subscription(request, False)

def resubscribe(request):
  return alter_subscription(request, True)

一些尚未显示的选项:

由于这是一个验证例程,请使用异常指示失败,使用正常的None(忽略)返回指示成功:

def verify_permissions(request):
  user = request.user
  sid = request.POST.get('subscription_id')
  try:
    sub = Subscription.objects.get(id=sid)
  except ObjectDoesNotExist:
    raise PermissionError, 'Given subscription does not exist.'
  if sub.user != user:
    raise PermissionError, 'Invalid permission.'

def subscribe(request):
  try:
    verify_permissions(request)
    sub.save()
    return ajax_response(True)
  except PermissionError, why:
    return ajax_response(False, [('subscription', why)])
或者,由于Python是动态类型的,显然可以通过两种不同的方式调用
ajax\u response
:返回用于构造响应的参数,并检查第一个参数的值

def verify_permissions(request, purpose):
  user = request.user
  sid = request.POST.get('subscription_id')
  try:
    sub = Subscription.objects.get(id=sid)
  except ObjectDoesNotExist:
    return (False, [(purpose, 'Given subscription does not exist.')]) 
  if sub.user != user:
    return (False, [(purpose, 'Invalid permission.')])
  return (True,)

def subscribe(request):
  result = verify_permissions(request, 'subscription')
  if result[0]: sub.save()
  return ajax_response(*result)

一些尚未显示的选项:

由于这是一个验证例程,请使用异常指示失败,使用正常的None(忽略)返回指示成功:

def verify_permissions(request):
  user = request.user
  sid = request.POST.get('subscription_id')
  try:
    sub = Subscription.objects.get(id=sid)
  except ObjectDoesNotExist:
    raise PermissionError, 'Given subscription does not exist.'
  if sub.user != user:
    raise PermissionError, 'Invalid permission.'

def subscribe(request):
  try:
    verify_permissions(request)
    sub.save()
    return ajax_response(True)
  except PermissionError, why:
    return ajax_response(False, [('subscription', why)])
或者,由于Python是动态类型的,显然可以通过两种不同的方式调用
ajax\u response
:返回用于构造响应的参数,并检查第一个参数的值

def verify_permissions(request, purpose):
  user = request.user
  sid = request.POST.get('subscription_id')
  try:
    sub = Subscription.objects.get(id=sid)
  except ObjectDoesNotExist:
    return (False, [(purpose, 'Given subscription does not exist.')]) 
  if sub.user != user:
    return (False, [(purpose, 'Invalid permission.')])
  return (True,)

def subscribe(request):
  result = verify_permissions(request, 'subscription')
  if result[0]: sub.save()
  return ajax_response(*result)

我实际上已经想到了它,并创建了函数
def\u toggle\u subscription(request,toggle\u to):
其中有一行
sub.is\u active=toggle\u to
。。。但是我觉得我已经利用了这样一个事实,即这个示例在提供的代码之间有如此小的差异。如果这两个函数之间的差异是可分性的呢?好吧,如果差异是相当大的,我不认为这算是代码重复。对不起,我想我没有具体说明。。。当我提到“差异”时,我的意思是指出非公共逻辑之间的差异。在提供的示例中,subscribe()和unsubscribe()之间的差异为sub.is_active=False(或True)。但是,如果#block和#endblock之间的代码只是初步检查,而后面的实际逻辑更复杂,该怎么办?在更复杂的情况下,您可以尝试第二个建议,使用常规的“无”结果。或者试试我的建议我实际上已经想到了它,并创建了函数
def\u toggle\u subscription(request,toggle\u to):
其中有一行
sub.is\u active=toggle\u to
。。。但是我觉得我已经利用了这样一个事实,即这个示例在提供的代码之间有如此小的差异。如果这两个函数之间的差异是可分性的呢?好吧,如果差异是相当大的,我不认为这算是代码重复。对不起,我想我没有具体说明。。。当我提到“差异”时,我的意思是指出非公共逻辑之间的差异。在提供的示例中,subscribe()和unsubscribe()之间的差异为sub.is_active=False(或True)。但是,如果#block和#endblock之间的代码只是初步检查,而后面的实际逻辑更复杂,该怎么办?在更复杂的情况下,您可以尝试第二个建议,使用常规的“无”结果。或者试试我的建议如果公共代码只进行验证,则从包装器调用它并检查返回值。如果这是一个django问题,并且您正在尝试进行验证,那么可以查看中间件或装饰器?但不要调用参数“
bool
”,因为这会掩盖一个内置项(类型的名称)。:)固定(关于“bool”)ty,Karl.:)如果公共代码只进行验证,则从包装器调用它并检查返回值。如果这是一个django问题,并且您正在尝试进行验证,那么可以查看中间件或装饰器,但不要调用参数“
boo”