Python中的自我语法

4
每当我定义一个有许多参数的类时,我经常会做这样的事情:
class myClass(object):
    def __init__(self,param1,param2,param3, ...):
         self.param1 = param1
         self.param2 = param2
         self.param3 = param3
 ...

我的问题是:有没有更智能、更Python风格的方法来完成这个任务?

谢谢, Alex。


可能很聪明,但如果你传递超过六个参数,你的代码可能会变得非常丑陋! - Alex S
在我看来,你所做的是最易读和最符合 Python 风格的。只有在特殊情况下,例如属性数量很大时,我才会使用其他选项。 - FogleBird
1
如果你经常向构造函数传递六个参数,并且直接将它们复制到属性中而没有进一步处理,那么你可能需要重新考虑一下清晰的API和良好的面向对象编程风格的概念。 - user395760
说实话,我的背景是数值分析和统计物理学,所以通常我写的代码需要多次运行或者需要访问内部工作方式,但它应该是自包含且可重用的。我不一定需要使用面向对象编程,但我认为我可以从中学到一些东西。例如,当你有一个热力学系统时,你会有大小、温度、相互作用强度、磁场等参数。也许用一个类来表示系统及其动态实际上是一个坏主意。 - Alex S
3个回答

9
您可以接受可变数量的命名参数并自动设置它们,就像这样:
class MyClass(object):
    def __init__(self, **kwargs): # variable named arguments
        for k, v in kwargs.items():
           setattr(self, k, v) # set the value of self.k to v, same as self.k = v


test = MyClass(param1="param1", param2="param2")
print test.param1 # "param1"

setattr文档


有点复杂,但肯定能完成任务。问题是每次使用它时我可能都要检查属性是否已定义。不过还是谢谢! - Alex S
1
由于这是在构造函数中,因此对象本身此时不具有属性,因此不需要检查。 - sean
1
另一件你有时会看到的事情是 self.__dict__.update(kwargs)。然而,我更喜欢这种方法。 - mgilson

3
您可以将参数作为关键字参数传递:-
def __init__(self, **kwargs):
     self.args = kwargs

那么,您将像这样实例化您的类:-
myClassObj = MyClass(a=12, b="abc") 

如果这样做,你的args字典将包含这些参数对:

{'a':12, 'b':'abc'}

访问属性的方法:

myClassObj.args['a']
myClassObj.args['b']

你也可以传递各种组合的参数。任何函数中都有4种参数类型:-
  • 位置参数
  • 默认参数
  • 非关键字参数
  • 关键字参数

仅按照上述顺序。因此,函数声明的典型语法为:-

def func(positional_arg, default_arg, *nkwargs, **kwargs)

有关定义函数的更多信息,请参见文档


那么我之后可以在类内部引用self.a和self.b吗? - Alex S
2
但是这并不能产生期望的结果。只会有一个属性args,而不是多个属性。 - Lev Levitsky
@AlexS.. 不是的,self.args 访问的是字典。然后要访问每个参数:- self.args['a'] - Rohit Jain
@LevLevitsky.. 是的,由于该属性是一个字典,它可以将所有这些属性存储在其中,然后我们可以访问它。请查看我的编辑帖子。 - Rohit Jain

0
你可以这样做:
def __init__(self,*args):
   _init_args = ('param1','param2','param3')
   if len(_init_args) != len(args):
      raise TypeError('__init__ takes {nargs} args'.format(nargs=len(_init_args)))
   for k,v in zip(_init_args,*args):
      setattr(self,k,v)

但我真的不认为这比你原来的解决方案或sean发布的解决方案好多少。与sean的答案相比,它的优点在于用户不需要知道您类中属性的名称。它的行为有点像声明函数:

def __init__(self,arg1,arg2,arg3):
    ...

虽然仍然存在差异。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接