首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在__init__中避免"self.x = x;self.y = y;self.z = z“模式?

如何在__init__中避免"self.x = x;self.y = y;self.z = z“模式?
EN

Stack Overflow用户
提问于 2016-02-04 09:22:42
回答 8查看 14.2K关注 0票数 171

我看到了这样的模式

def __init__(self, x, y, z):
    ...
    self.x = x
    self.y = y
    self.z = z
    ...

非常频繁,通常有更多的参数。有没有好的方法来避免这种乏味的重复?这个类应该从namedtuple继承吗?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2016-02-04 15:24:51

编辑:如果您有python 3.7+,只需使用dataclasses

一个保持签名的装饰器解决方案:

import decorator
import inspect
import sys


@decorator.decorator
def simple_init(func, self, *args, **kws):
    """
    @simple_init
    def __init__(self,a,b,...,z)
        dosomething()

    behaves like

    def __init__(self,a,b,...,z)
        self.a = a
        self.b = b
        ...
        self.z = z
        dosomething()
    """

    #init_argumentnames_without_self = ['a','b',...,'z']
    if sys.version_info.major == 2:
        init_argumentnames_without_self = inspect.getargspec(func).args[1:]
    else:
        init_argumentnames_without_self = tuple(inspect.signature(func).parameters.keys())[1:]

    positional_values = args
    keyword_values_in_correct_order = tuple(kws[key] for key in init_argumentnames_without_self if key in kws)
    attribute_values = positional_values + keyword_values_in_correct_order

    for attribute_name,attribute_value in zip(init_argumentnames_without_self,attribute_values):
        setattr(self,attribute_name,attribute_value)

    # call the original __init__
    func(self, *args, **kws)


class Test():
    @simple_init
    def __init__(self,a,b,c,d=4):
        print(self.a,self.b,self.c,self.d)

#prints 1 3 2 4
t = Test(1,c=2,b=3)
#keeps signature
#prints ['self', 'a', 'b', 'c', 'd']
if sys.version_info.major == 2:
    print(inspect.getargspec(Test.__init__).args)
else:
    print(inspect.signature(Test.__init__))
票数 86
EN

Stack Overflow用户

发布于 2016-02-04 09:27:34

显式比隐式好...所以,你可以让它变得更简洁:

def __init__(self,a,b,c):
    for k,v in locals().items():
        if k != "self":
             setattr(self,k,v)

更好的问题是:你应该这样做吗?

..。也就是说,如果你想要一个命名的元组,我推荐使用命名的元组(记住,元组有一定的附加条件)……也许你想要一个OrderedDict或者仅仅是一个字典..。

票数 30
EN

Stack Overflow用户

发布于 2016-02-04 10:48:06

正如其他人所提到的,重复是不错的,但在某些情况下,命名元组可能非常适合这种类型的问题。这避免了使用locals()或kwargs,这通常不是一个好主意。

from collections import namedtuple
# declare a new object type with three properties; x y z
# the first arg of namedtuple is a typename
# the second arg is comma-separated or space-separated property names
XYZ = namedtuple("XYZ", "x, y, z")

# create an object of type XYZ. properties are in order
abc = XYZ("one", "two", 3)
print abc.x
print abc.y
print abc.z

我发现它的用法有限,但你可以像继承任何其他对象一样继承一个命名元组(示例继续):

class MySuperXYZ(XYZ):
    """ I add a helper function which returns the original properties """
    def properties(self):
        return self.x, self.y, self.z

abc2 = MySuperXYZ(4, "five", "six")
print abc2.x
print abc2.y
print abc2.z
print abc2.properties()
票数 29
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35190877

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档