[英]Pythonic way to assign the parameter into attribute?
示例代碼如下:
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個參數,則會受到影響。 有沒有人對這個更方便的方法有想法?
你可以這樣做:
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集。
顯式優於隱式
def assign(self, input=None, output=None, param=None, p1=None, p2=None):
有很多優點
def assign(self, **kwargs)
assign
則會引發有用的TypeError
。 assign
值得贊揚的是,OP發布的代碼完全是明確的,盡管if
statement是單調的。 要減少單調,你可以使用這樣的東西:
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')
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
使用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,)
???
說真的嗎?
哦,哎呀!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.