Ada*_*tan 75 python class initialization-list
我有一个python类,看起来像这样:
class Process:
def __init__(self, PID, PPID, cmd, FDs, reachable, user):
Run Code Online (Sandbox Code Playgroud)
其次是:
self.PID=PID
self.PPID=PPID
self.cmd=cmd
...
Run Code Online (Sandbox Code Playgroud)
有没有办法自动初始化这些实例变量,比如C++的初始化列表?它会节省大量冗余代码.
Nad*_*mli 89
你可以使用装饰器:
from functools import wraps
import inspect
def initializer(func):
"""
Automatically assigns the parameters.
>>> class process:
... @initializer
... def __init__(self, cmd, reachable=False, user='root'):
... pass
>>> p = process('halt', True)
>>> p.cmd, p.reachable, p.user
('halt', True, 'root')
"""
names, varargs, keywords, defaults = inspect.getargspec(func)
@wraps(func)
def wrapper(self, *args, **kargs):
for name, arg in list(zip(names[1:], args)) + list(kargs.items()):
setattr(self, name, arg)
for name, default in zip(reversed(names), reversed(defaults)):
if not hasattr(self, name):
setattr(self, name, default)
func(self, *args, **kargs)
return wrapper
Run Code Online (Sandbox Code Playgroud)
用它来装饰__init__方法:
class process:
@initializer
def __init__(self, PID, PPID, cmd, FDs, reachable, user):
pass
Run Code Online (Sandbox Code Playgroud)
输出:
>>> c = process(1, 2, 3, 4, 5, 6)
>>> c.PID
1
>>> dir(c)
['FDs', 'PID', 'PPID', '__doc__', '__init__', '__module__', 'cmd', 'reachable', 'user'
Run Code Online (Sandbox Code Playgroud)
Kiv*_*Kiv 35
如果您使用的是Python 2.6或更高版本,则可以使用collections.namedtuple:
>>> from collections import namedtuple
>>> Process = namedtuple('Process', 'PID PPID cmd')
>>> proc = Process(1, 2, 3)
>>> proc.PID
1
>>> proc.PPID
2
Run Code Online (Sandbox Code Playgroud)
这是合适的,特别是当你的班级真的只是一大堆价值观.
Jun*_*ius 28
对于Python 3.7+,您可以使用数据类,这是一种非常pythonic和可维护的方式来做你想要的.
它允许您为类定义字段,这些字段是自动初始化的实例变量.
看起来像这样:
@dataclass
class Process:
PID: int
PPID: int
cmd: str
...
Run Code Online (Sandbox Code Playgroud)
该__init__方法已经在您的课程中.
注意,这里类型提示是必需的,这就是为什么我已经使用int并str在本例中.如果您不知道字段的类型,可以使用模块中的Anytyping.
与提出的解决方案相比,Data Class具有许多优点:
**kwargs.__init__.__post_init__使用该__init__方法.Joc*_*zel 21
你可以做的另一件事:
class X(object):
def __init__(self, a,b,c,d):
vars = locals() # dict of local names
self.__dict__.update(vars) # __dict__ holds and object's attributes
del self.__dict__["self"] # don't need `self`
Run Code Online (Sandbox Code Playgroud)
但我推荐的唯一解决方案,除了拼写出来之外,还是"在你的编辑器中创建一个宏";-p
Sil*_*ost 15
您可以使用关键字参数轻松完成,例如:
>>> class D:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
>>> D(test='d').test
'd'
Run Code Online (Sandbox Code Playgroud)
位置参数的类似实现将是:
>> class C:
def __init__(self, *args):
self.t, self.d = args
>>> C('abc', 'def').t
'abc'
>>> C('abc', 'def').d
'def'
Run Code Online (Sandbox Code Playgroud)
对我来说似乎没有解决你的问题.
Nadia的解决方案更好,更强大,但我认为这也很有趣:
def constructor(*arg_names):
def __init__(self, *args):
for name, val in zip(arg_names, args):
self.__setattr__(name, val)
return __init__
class MyClass(object):
__init__ = constructor("var1", "var2", "var3")
>>> c = MyClass("fish", "cheese", "beans")
>>> c.var2
"cheese"
Run Code Online (Sandbox Code Playgroud)
我出于相同的目的需要一些东西,但是现有的答案都没有涵盖我测试过的所有案例。Nadia的答案最接近我想要的答案,因此我以她的代码作为基础。
下面的装饰器适用于所有有效的参数组合:
Positional __init__(self, a, b )
Keyword __init__(self, a=None, b=None )
Positional + Keyword __init__(self, a, b, c=None, d=None)
Variable Positional __init__(self, *a )
Variable Positional + Keyword __init__(self, *a, b=None )
Variable Positional + Variable Keyword __init__(self, *a, **kwargs )
Positional + Variable Positional + Keyword __init__(self, a, *b, c=None )
Positional + Variable Positional + Variable Keyword __init__(self, a, *b, **kwargs )
Keyword Only __init__(self, *, a=None )
Positional + Keyword Only __init__(self, a, *, b=None )
Run Code Online (Sandbox Code Playgroud)
它还实现了标准的_-prefix约定,以允许__init__-private变量不会分配给类实例。
Positional __init__(self, a, b )
Keyword __init__(self, a=None, b=None )
Positional + Keyword __init__(self, a, b, c=None, d=None)
Variable Positional __init__(self, *a )
Variable Positional + Keyword __init__(self, *a, b=None )
Variable Positional + Variable Keyword __init__(self, *a, **kwargs )
Positional + Variable Positional + Keyword __init__(self, a, *b, c=None )
Positional + Variable Positional + Variable Keyword __init__(self, a, *b, **kwargs )
Keyword Only __init__(self, *, a=None )
Positional + Keyword Only __init__(self, a, *, b=None )
Run Code Online (Sandbox Code Playgroud)
我包括了测试,但是为了简洁起见,将它们折叠到最后一行(58)。您可以通过用换行符为find/replace所有$字符- 展开详细描述所有潜在用例的测试。