我有一个类,在实例化时提供了很多属性( init )。
看起来像这样,但还有大约30个attr:
class SomeObject:
def __init__(self,
first,
second):
self.first = first
self.second = second
工作正常,但重复性很长,很难更新。
在我使用更小的课程之前:
class SomeObject:
def __init__(self, **attr):
self.__dict__.update(attr)
工作正常,更容易,但很难跟踪。当使用IDE(我使用PyCharm)时,我在编写对象时没有提示,自动完成提示通常不起作用。
我会寻找两个类的混合,例如:
class SomeObject:
def __init__(self,
first,
second):
self.__dict__.update(???) # I would like to do it in a single line, so I dont have to write a new attr two (three...) times.
有谁知道这是否可行?非常感谢
Python 3.4 + PyCharm 2016.1 CommunityEdition
...编辑/补充......
问题似乎主要在于"保留" IDE中的代码检查,以便对象上仍然可以使用自动完成等。
答案 0 :(得分:2)
您只需使用locals
内置函数获取本地变量的字典,然后删除self
并更新:
class test:
def __init__(self,
a,b,c,d,e,f,g,h,i,j,k,l,m,
n,o,p,q,r,s,t,u,v,w,x,y,z):
args = locals()
del args["self"]
if "args" in args:
del args["args"]
self.__dict__.update(args)
args = list(range(26))
x = test(*args)
from string import ascii_lowercase as letters
assert args == [getattr(x,c) for c in letters]
print("worked")
虽然如果你真的想让你的IDE开心,它需要看到显式的属性赋值,所以你可以编写代码来编写代码:
def write_init_code(func):
self,*args = func.__code__.co_varnames
return "\n".join(["{0}.{1} = {1}".format(self,a)
for a in args])
class test:
def __init__(self,a,b,c,d,e,f,*v,**kw):
pass #just a moment...
print(write_init_code(test.__init__))
然后只需将write_init_code
的结果复制粘贴并缩进到实际功能中即可完成。
答案 1 :(得分:1)
模块inspect
允许您查询正在运行的程序。以下示例演示了它的用法:
import inspect
class Test:
def __init__(self, a, b, c, d):
argInfo = inspect.getargvalues(inspect.currentframe())
print(argInfo)
# Print argument values in order of parameters
print([ argInfo.locals[paramName] for paramName in argInfo.args[1:] ])
t = Test(1,2,3,4)
输出:
ArgInfo(args=['self', 'a', 'b', 'c', 'd'], varargs=None, keywords=None, locals={'c': 3, 'self': <__main__.Test object at 0x7fb2d9c0ce10>, 'b': 2, 'd': 4, 'a': 1})
[1, 2, 3, 4]
如您所见,您可以通过ArgInfo.locals
访问参数字典及其相应的参数名称。
第二个打印出来的例子是如何按参数声明的顺序放置参数值。
您可以使用它来填充实例变量,或者只需复制ArgInfo.locals
字典。
答案 2 :(得分:0)
您可以使用locals()
来实现您的目标:
class SomeObject:
def __init__(self, first, second):
kwargs = locals()
kwargs.pop('self') # remove `self` keywork from the dict
self.__dict__.update(kwargs)
答案 3 :(得分:0)
有了dataclasses
,PyCharm现在很容易并且完全支持。通过添加键入注释并使用修饰符@dataclasses.dataclass
,我们使类成员充当实例成员。
import dataclasses
import typing
@dataclasses.dataclass
class SomeObject:
first: str
second: str
class_member1 = None
class_member2: typing.ClassVar[str] = None
SomeObject(first="first", second="second")
请注意,带有诸如first
和second
之类的注释的类字段的作用类似于实例成员。而诸如class_member1
之类的未注释字段仍保留为类成员。
但是,如果您想将某个字段用作类成员,但仍然希望拥有键入信息,请使用注释typing.ClassVar
。这样,您就可以拥有class_member2
这是一个班级成员,并且还具有键入信息。
答案 4 :(得分:-1)
原始答案: 使用PyCharm中的多个游标,您可以轻松转换
self.first = first
self.second = second
到很长的一行,如:
self.first, self.second = first, second
这就是我为保持PyCharm智能而做的事情