代码之家  ›  专栏  ›  技术社区  ›  mk12

python初始化参数?

  •  5
  • mk12  · 技术社区  · 15 年前

    似乎经常 __init__ 方法与此类似:

    def __init__(self, ivar1, ivar2, ivar3):
        self.ivar1 = ivar1
        self.ivar2 = ivar2
        self.ivar3 = ivar3
    

    有没有办法把论点变成一个清单 *args **kwargs )然后使用 setattr 要设置实例变量,参数的名称和传递的参数是什么?可能还需要对列表进行切片,例如至少需要将其切片到 [1:] 因为你不想 self.self .

    (实际上,我想需要一本字典来保存名称和值)

    这样地:

    def __init__(self, ivar1, ivar2, ivar3, optional=False):
        for k, v in makedict(self.__class__.__init__.__args__): # made up __args__
            setattr(self, k, v)
    

    谢谢!

    在回答未知答案时,我发现这是可行的:

    Class A(object):
        def __init__(self, length, width, x):
            self.__dict__.update(dict([(k, v) for k, v in locals().iteritems() if k != 'self']))
    

    Class A(object):
        def __init__(self, length, width, x):
            self.__dict__.update(locals())
            del self.__dict__['self']
    

    还不错。

    8 回复  |  直到 12 年前
        1
  •  7
  •   Unknown    15 年前

    干得好。是的,这是一个丑陋的邪恶黑客。是的,对象需要一个变量。但是,嘿,这是一个整洁的小班轮!

    def __init__(self):
        self.__dict__.update(locals())
    

    构造函数可以接受任何类型的参数。

    class test(object):
        def __init__(self, a, b, foo, bar=5)...
    
    a = test(1,2,3)
    dir(a)
    
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'foo', 'bar', 'self']
    

    它也将包含self,但是您可以轻松地删除它或使自己的更新函数忽略self。

        2
  •  6
  •   Ants Aasma    15 年前

    您可以使用inspect.getargspec并将其封装为装饰器。查找可选参数和关键字参数有点困难,但应该这样做:

    def inits_args(func):
        """Initializes object attributes by the initializer signature"""
        argspec = inspect.getargspec(func)
        argnames = argspec.args[1:]
        defaults = dict(zip(argnames[-len(argspec.defaults):], argspec.defaults))
        @functools.wraps(func)
        def __init__(self, *args, **kwargs):
            args_it = iter(args)
            for key in argnames:
                if key in kwargs:
                    value = kwargs[key]
                else:
                    try:
                        value = args_it.next()
                    except StopIteration:
                        value = defaults[key]
                setattr(self, key, value)
            func(self, *args, **kwargs)
        return __init__
    

    然后您可以这样使用它:

    class Foo(object):
        @inits_args
        def __init__(self, spam, eggs=4, ham=5):
            print "Foo(%r, %r, %r)" % (self.spam, self.eggs, self.ham)
    
        3
  •  4
  •   Ned Batchelder    15 年前

    如果参数是在函数签名中单独指定的,那么将它们作为列表获取是没有好方法的。您可能可以使用inspect或framehack来做一些事情,但这比简单地像您所做的那样拼写出来还要糟糕。

        4
  •  3
  •   Cristian Ciupitu    15 年前

    尝试 inspect.getargspec :

    In [31]: inspect.getargspec(C.__init__)
    
    Out[31]: ArgSpec(args=['self', 'ivar1', 'ivar2', 'ivar3', 'optional'],
    
                     varargs=None, keywords=None, defaults=(False,))
    
        5
  •  2
  •   PaulMcG    15 年前

    看看collections模块中的新名称duple(python 2.6中的新名称)是否适合您。

        6
  •  2
  •   Lennart Regebro    15 年前

    您可以使用自省参数来完成这项工作,但是代码将比您试图替换的代码长。尤其是当你处理千瓦时,你可能不得不这样做。

    这种短代码在大多数情况下都有效(从未知示例改进而来):

    >>> class Foo:
    ...   def __init__(self, labamba, **kw):
    ...       params = locals().copy()
    ...       del params['self']
    ...       if 'kw' in params:
    ...           params.update(params['kw'])
    ...           del params['kw']
    ...       self.__dict__.update(params)
    

    但这是一个丑陋的黑客,使代码的可读性下降,除了懒惰,没有任何特殊的原因,所以不要这样做。而且,你多久一次 真的? 有超过5-6个init参数的类吗?

        7
  •  1
  •   qweasd    15 年前

    我最喜欢这种形式,不会太长,既可以复制粘贴,也可以分类:

    class DynamicInitClass(object):
          __init_defargs=('x',)
          def __init__(self,*args,**attrs):
            for idx,val in enumerate(args): attrs[self.__init_defargs[idx]]=val
            for key,val in attrs.iteritems(): setattr(self,key,val)
    
        8
  •  0
  •   ilya n.    15 年前

    从一个特殊的类派生如何?我想是 更明确、更灵活 这种方式:

    class InitMe:
        def __init__(self, data):
            if 'self' in data:
                 data = data.copy()
                 del data['self']
            self.__dict__.update(data)
    
    
    class MyClassA(InitMe):
        def __init__(self, ivar1, ivar2, ivar3 = 'default value'):
            super().__init__(locals())
    
    
    class MyClassB(InitMe):
        def __init__(self, foo):
            super().__init__({'xxx': foo, 'yyy': foo, 'zzz': None})
    # or    super().__init__(dict(xxx=foo, yyy=foo, zzz=None))
    
    class MyClassC(InitMe):
        def __init__(self, foo, **keywords):
            super().__init__(keywords)