说,我在Python中有以下类
class Foo(object):
a = None
b = None
c = None
def __init__(self, a = None, b = None, c = None):
self.a = a
self.b = b
self.c = c
有没有办法简化这个过程?每当我向Foo类添加一个新成员时,我都被迫修改构造函数。
答案 0 :(得分:30)
请注意
class Foo(object):
a = None
在Foo
的词典中设置一个键值对:
Foo.__dict__['a']=None
,而
def __init__(self, a = None, b = None, c = None):
self.a = a
在Foo实例对象的dict中设置一个键值对:
foo=Foo()
foo.__dict__['a']=a
因此,在定义的顶部设置类成员与定义的下半部分中的实例属性的设置没有直接关系(在__init__
内。
另外,最好注意__init__
是Python的初始值设定项。 __new__
是类构造函数。
如果您正在寻找一种基于__init__
参数自动添加一些实例属性的方法,您可以使用:
import inspect
import functools
def autoargs(*include,**kwargs):
def _autoargs(func):
attrs,varargs,varkw,defaults=inspect.getargspec(func)
def sieve(attr):
if kwargs and attr in kwargs['exclude']: return False
if not include or attr in include: return True
else: return False
@functools.wraps(func)
def wrapper(self,*args,**kwargs):
# handle default values
for attr,val in zip(reversed(attrs),reversed(defaults)):
if sieve(attr): setattr(self, attr, val)
# handle positional arguments
positional_attrs=attrs[1:]
for attr,val in zip(positional_attrs,args):
if sieve(attr): setattr(self, attr, val)
# handle varargs
if varargs:
remaining_args=args[len(positional_attrs):]
if sieve(varargs): setattr(self, varargs, remaining_args)
# handle varkw
if kwargs:
for attr,val in kwargs.iteritems():
if sieve(attr): setattr(self,attr,val)
return func(self,*args,**kwargs)
return wrapper
return _autoargs
所以当你说
时class Foo(object):
@autoargs()
def __init__(self,x,path,debug=False,*args,**kw):
pass
foo=Foo('bar','/tmp',True, 100, 101,verbose=True)
您自动获取这些实例属性:
print(foo.x)
# bar
print(foo.path)
# /tmp
print(foo.debug)
# True
print(foo.args)
# (100, 101)
print(foo.verbose)
# True
PS。虽然我写了这篇文章(为了好玩),但我不建议使用autoargs
进行认真的工作。明确是简单,明确和绝对正确的。我不能对autoargs
说同样的话。
<击> PPS。它只是我,还是在Stackoverflow上打破了很多按钮?编辑器窗口丢失了所有图标... :( 清除浏览器缓存修复了问题。
答案 1 :(得分:12)
有elegant个方法可以做到这一点。
有没有办法简化这个过程?每当我向Foo类添加一个新成员时,我都被迫修改构造函数。
还有粗略方式。它会工作,但不推荐。看到并决定。
>>> class Foo(object):
def __init__(self, **attrs):
self.__dict__.update(**attrs)
def __getattr__(self, attr):
return self.__dict__.get(attr, None)
>>> f = Foo(a = 1, b = 2, c = 3)
>>> f.a, f.b
(1, 2)
>>> f = Foo(bar = 'baz')
>>> f.bar
'baz'
>>> f.a
>>>
关键字参数构造函数可让您在不明确定义任何参数的情况下离开。 警告:这违背了“明确胜于隐性”的原则。
如果要为不存在的属性返回默认值而不是获取__getattr__
,则只需覆盖AttributeError
。
答案 2 :(得分:3)
Python 3.7提供了dataclasses
,在这种情况下非常有用:
from dataclasses import dataclass
@dataclass
class Foo:
a: str = None
b: str = None
c: str = None
这使您不必只想存储一些属性就不必写出__init__
方法。
为您提供了一种不错的__repr__
方法:
>>> a = Foo()
>>> a
Foo(a=None, b=None, c=None)
另请参阅namedtuple:
from collections import namedtuple
Foo = namedtuple('Foo', ['a', 'b', 'c'])
尽管所有字段都是namedtuple所必需的。
>>> a = Foo(1, 2, 3)
>>> a
Foo(a=1, b=2, c=3)
答案 3 :(得分:-1)