示例代码如下:
def assign(self, input=None, output=None, param=None, p1=None, p2=None):
if input:
self.input = input
if output:
self.output = output
if param:
self.param = param
if p1:
self.p1 = p1
if p2:
self.p2 = p2
虽然这看起来非常清楚,但如果此功能有10个参数,则会受到影响。有没有人对这种更方便的方法有想法?
答案 0 :(得分:7)
你可以这样做:
def assign(self,**kwargs):
for k,v in kwargs.items():
if v:
setattr(self,k,v)
这很简单,适合很多情况。如果您想维护一组您可以接受的关键字,并为其余关键字引发TypeError:
#python2.7 and newer
def assign(self,allowed_kwargs={'foo','bar','baz'},**kwargs):
if kwargs.keysview() - allowed_kwargs:
raise TypeError('useful message here...')
for k in allowed_kwargs:
setattr(self,k,kwargs[k])
这也是可以检查的,因为用户将看到允许的kwargs集。
答案 1 :(得分:1)
明确优于隐式
def assign(self, input=None, output=None, param=None, p1=None, p2=None):
比
有很多优点def assign(self, **kwargs)
TypeError
assign
。assign
值得赞扬的是,OP发布的代码完全是明确的,尽管if
- 语句是单调的。要减少单调,
你可以使用这样的东西:
class Foo(object):
def assign(self, input=None, output=None, param=None, p1=None, p2=None):
for name in 'input output param p1 p2'.split():
val = vars()[name]
if val is not None:
setattr(self, name, val)
foo = Foo()
foo.assign(p1=123, p2='abc')
答案 2 :(得分:0)
python的一大优点是它的交互式解释器。当你编写这样的代码时:
>>> def assign(self, input=None, output=None, param=None, p1=None, p2=None):
... pass
...
很容易弄清楚你应该如何使用这个功能:
>>> help(assign)
Python Library Documentation: function assign in module __main__
assign(self, input=None, output=None, param=None, p1=None, p2=None)
相比之下:
>>> def assign2(self, **kwargs):
... pass
...
给出:
>>> help(assign2)
Python Library Documentation: function assign2 in module __main__
assign2(self, **kwargs)
我希望你理解为什么第一种形式是可取的。但是你仍然希望避免两次写入(在参数和正文中)。
第一个问题是为什么你在编写这种性质的代码?我发现这是一个非常常见的情况,我想要一个具有一堆属性的类,它将随身携带,但这些属性的集合基本上是固定的。在最常见的情况下,这些属性永远不会在对象的生命周期中发生变化;在这种情况下,python有一个内置的帮助器!
>>> import collections
>>> Assignment = collections.namedtuple('Assignment', 'input output param p1 p2')
>>> assign = Assignment(None, None, None, None, None)._replace
>>> assign(p1=10)
Assignment(input=None, output=None, param=None, p1=10, p2=None)
>>> help(Assignment)
Python Library Documentation: class Assignment in module __main__
class Assignment(__builtin__.tuple)
| Assignment(input, output, param, p1, p2)
|
... SNIP
namedtuple
是常规类,您可以从它们继承它们以给它们特殊的行为。不幸的是,它们是不可改变的,如果你碰巧需要它,你将需要另一种技术;但你应该首先达到命名元组。否则,我们可以利用其他一些魔法;我们可以得到所有的局部变量,它们在函数开始时只包含参数:
>>> class Assignable(object):
... def assign(self, input=None, output=None, param=None, p1=None, p2=None):
... _kwargs = vars()
... _kwargs.pop('self')
... vars(self).update((attr, value) for attr, value in _kwargs.items() if value is not None)
...
>>> a = Assignable()
>>> vars(a)
{}
>>> a.assign(p1=6)
>>> vars(a)
{'p1': 6}
>>> a.p1
6
并且help()
文字仍然非常有用!
>>> help(a.assign)
Python Library Documentation: method assign in module __main__
assign(self, input=None, output=None, param=None, p1=None, p2=None) method of __main__.Assignable instance
答案 3 :(得分:0)
使用mgilson和unutbu的解决方案,写入所有类型的呼叫的可能性都将丢失。
在我的以下解决方案中,这种可能性得以保留:
class Buu(object):
def assign(self,
input=None, output=None,
param=None,
p1=None, p2=None,
**kw):
for k,v in locals().iteritems():
if v not in (self,None,kw):
if v == (None,):
setattr(self,k,None)
else:
setattr(self,k,v)
for k,v in kw.iteritems():
setattr(self,k,v)
buu = Buu()
buu.assign(None,(None,), p1=[])
print "buu's attributes:",vars(buu)
print
buu.assign(1,p2 = 555, xx = 'extra')
print "buu's attributes:",vars(buu)
结果
buu's attributes: {'output': None, 'p1': []}
buu's attributes: {'p2': 555, 'output': None, 'xx': 'extra', 'p1': [], 'input': 1}
顺便说一句,当编码器将None
作为参数的默认参数时,这是因为他预见到不会有必要将None
作为重要参数传递给在执行期间真的会有影响力
因此,我认为将None
作为真正重要的论点传递是一个错误的问题
但是,在上面的代码中,通过使用约定来避免此问题,以防必须创建值为None
的新属性,参数应为(None,)
。
如果有人想通过(None,)
???
说真的?
哎呀!