假设我有很多类似的表情
class X:
def __init__(self, a,b,c,d,e,f):
self.a = a
self.b = b
self.c = c
self.d = d
self.e = e
self.f = f
是否有一种优雅的方式来重写它?
谢谢!
答案 0 :(得分:3)
您可以尝试使用命名的generic arguments:
class X:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
然后:
x = X(a=1, b=2, c=3, d=4, e=5, f=6)
但这不是一个好习惯,因为它无法控制实际传递的内容。
或者:
class X:
def __init__(self, *args):
for key, value in zip(['a', 'b', 'c', 'd', 'e', 'f'], args):
setattr(self, key, value)
然后:
x = X(1, 2, 3, 4, 5, 6)
但是,正如Zen of Python所说:
显式优于隐式
您的原始代码就足够了!
编辑
为了避免覆盖危险属性,请替换
setattr(self, key, value)
使用
if not hasattr(self, key):
setattr(self, key, value)
答案 1 :(得分:3)
class X:
def __init__(self, a,b,c,d,e,f):
self.a = a
self.b = b
self.c = c
self.d = d
self.e = e
self.f = f
class X:
def __init__(self, *args):
arglist = ['a', 'b', 'c', 'd']
for i in range(0, len(arglist):
try:
setattr(self, arglist[i], args[i])
except IndexError:
raise Exception('Arg {} needs to be given a value'.format(arglist[i]))
看起来不是最优雅的东西,但是列表越长越简化,您也只需修改arglist即可反映出来。不好的是,您丢失了签名(您可能做出的所有非运行时检查都丢失了,例如您的IDE会发疯
其他建议包括枚举(使用索引的更清洁方式)。
或者您可以只使用zip,然后在开始时进行检查:
class X:
def __init__(self, *args):
arglist = ['a', 'b', 'c', 'd']
if len(arglist) != len(args):
raise CustomExceptino('Too few/many arguments...')
for keyval_tuple in zip(arglist, args):
setattr(self, keyval_tuple[0], keyval_tuple[1])
请注意,您仍然可以添加不具有这种行为的参数:
class X:
def __init__(self, special_arg, *args):
self.special_consequence = self.do_sth_with_special_arg(special_arg)
arglist = ['a', 'b', 'c', 'd']
if len(arglist) != len(args):
raise CustomExceptino('Too few/many arguments...')
for keyval_tuple in zip(arglist, args):
setattr(self, keyval_tuple[0], keyval_tuple[1])
答案 2 :(得分:3)
从Python 3.7开始,可以使用data classes
@dataclass
class X:
a: int
b: str
c: float
# etc...
dataclass
装饰器会自动生成合适的__init__
方法。
正如@Lie Ryan所说,您也可以使用namedtuple:
>>> X = namedtuple('X', ('a', 'b', 'c'))
>>> x = X(1, 2, 3)
>>> x
X(a=1, b=2, c=3)
>>> x.a
1
甚至可以继承添加或重载方法:
>>> class X(namedtuple('XSuper', ('a', 'b', 'c'))):
... def __repr__(self):
... return 'pouet'
...
>>> x = X(1, 2, 3)
>>> x
pouet
>>> x.a
1
fountainhead的答案也是一个与版本无关的绝妙技巧。
答案 3 :(得分:3)
您可以尝试以下方法:
class X:
def __init__(self, a,b,c,d,e,f):
all_l = locals() # Let this be the first statement.
for l in all_l:
if (l != 'self'):
self.__dict__[l] = all_l[l]
输出:
x = X(10,20,30,40,50,60)
print (x.d)
40