最佳实践:处理具有大量参数和保留名称的函数

2024-06-16 10:18:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在研究一个python client for the api乌斯吉。它我发现有必要编写接受许多(可选)参数的方法,这些参数将通过http请求发送。在

最初,我想声明用户可以插入哪些参数,因为它们太多了,所以我认为对于用户来说,使用一个列表作为参数,而不是让他自由地在dict中插入任何内容,这样更容易、更安全,最后我得到了这样的结果:

def alarms(self, container=None, _class=None, color=None,
           vassal=None, level=None, line=None, filename=None, 
           func=None, with_total=None, range=None):
    params = {k: v for k, v in locals().iteritems() if k != 'self' and v}
    if '_class' in params:
        params['class'] = params['_class']
        del params['_class']
    return self.get('alarms', params)

但是它很难看,我真的不喜欢用这种方式来处理''u class'参数。所以我想到的另一种可能性是接受一个可以包含任何内容(或**kwargs)的字典,在docstring中列出接受的键,然后清理输入。一种可能的方法是声明一个只接受允许参数的“private”方法。但同样的问题又出现了!有什么建议吗?对于有这么多参数的方法有什么最佳实践吗?在


Tags: the方法用户inselfclientnone声明
3条回答

当一个方法开始需要许多输入时,需要考虑的一个软件设计实践就是声明一个特殊的类,其中包含每个输入值的属性,然后您就可以从它的使用中分别实例化和填充它。这样,您只需将一个引用传递到方法签名(到封装类)中,而不是对每个属性的引用。随着对象模型的增长,您甚至可以添加构建器和验证方法来帮助您轻松地生成新类,并在需要时验证它的属性。在

How to define a class in Python

另外,考虑设计模式和可靠的设计原则,作为改进代码形式、功能和可维护性的方法。对这些模式非常熟悉,你将拥有真正提升游戏水平所需的知识,并从一名软件程序员转变为一名领导或工程师。在

http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29

http://en.wikipedia.org/wiki/Encapsulation_%28object-oriented_programming%29

http://en.wikipedia.org/wiki/Software_design_pattern

为了理清逻辑,你可以做的一件事是将你的听写理解改为:

params = {k.strip("_"): v for k, v in locals().iteritems() if k != 'self' and v is not None}
#          ^^^^^^^^^^^

那么您就不需要对类做任何事情;而且,我可能会使用class_而不是{},因为后者表示参数是“private”,但前者通常是“我需要使用关键字作为标识符”的提示

我同意使用**kwargs是一个好主意,而且可以使用set轻松清理它的键。我使用的是Python2.6,所以我没有设置理解,但是我的代码应该很容易翻译成更现代的版本。在

FWIW,我昨晚发布了这个程序的一个版本,但后来我决定它应该对坏参数做些什么,所以我临时删除了它。这是修改后的版本。在

验证_参数py

#! /usr/bin/env python

''' Validate the keys in kwargs

    Test keys against a container (set, tuple, list) of good keys,
    supplying a value of None for missing keys

    Also, if a key ends with an underscore, strip it.

    Written by PM 2Ring 2014.11.15

    From 
    http://stackoverflow.com/questions/26945235/best-practice-handle-functions-with-lots-of-parameters-and-reserved-names

'''

import sys

def test(**kwargs):
    good_keys = ("container", "class_", "color", 
        "vassal", "level", "line", "filename", 
        "func", "with_total", "range")
    new_kwargs = validate_keys(kwargs, good_keys)
    for t in new_kwargs.items():
        print "%-12s : %r" % t


#def alarms(**kwargs):
    #good_keys = ("container", "class_", "color", 
        #"vassal", "level", "line", "filename", 
        #"func", "with_total", "range")
    #return self.get('alarms', validate_keys(kwargs, good_keys))


def validate_keys(kwargs, good_keys):
    good_keys = set(good_keys)
    bad_keys = set(kwargs.keys()) - good_keys
    if bad_keys:
        bad_keys = ', '.join(bad_keys)
        print >>sys.stderr, "Unknown parameters: %s\n" % bad_keys
        raise KeyError, bad_keys

    new_kwargs = {}  
    for k in good_keys:
        new_kwargs[k.rstrip('_')] = kwargs.get(k, None)
    return new_kwargs


test(color="red", class_="top",
    #bar=1, foo=3,  #Some bad keys
    level=2, func="copy",filename="text.txt")

输出

^{pr2}$

相关问题 更多 >