将一个自定义类的序列映射到另一个自定义类的python方法是什么?

将一个自定义类的序列映射到另一个自定义类的python方法是什么?,python,type-conversion,Python,Type Conversion,…或者,C的Select的Python版本是什么。。。方法 给定自定义类a的列表l,最重要的是什么?将l的每个元素映射到不同自定义类B的Python方法 例如,下面的代码可以做到这一点,但这是最具python风格的方法吗?注意,实类型有许多属性 l = [A('Greg', 33), A('John', 39)] def map_to_type_b(the_list): new_list = [] for item in the_list: new_list.a

…或者,C的Select的Python版本是什么。。。方法

给定自定义类a的列表l,最重要的是什么?将l的每个元素映射到不同自定义类B的Python方法

例如,下面的代码可以做到这一点,但这是最具python风格的方法吗?注意,实类型有许多属性

l = [A('Greg', 33), A('John', 39)]

def map_to_type_b(the_list):
    new_list = []
    for item in the_list:
        new_list.append(B(item.name, item.age))

    return new_list

l2 = map_to_type_b(l)

我来自C背景,我会使用LinQ select或select extensions方法从源序列投影到类型B的新序列。

我会说,B类的工作的一部分是确定如何将某个任意其他类的实例转换为B的实例,因此,我将使用类方法替代构造函数方法,例如:

class A(object):

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return 'A({0.name!r}, {0.age!r})'.format(self)


class B(A):

    def __repr__(self):
        return 'B({0.name!r}, {0.age!r})'.format(self)

    @classmethod
    def from_A(cls, inst):
        return cls(inst.name, inst.age)
然后,您可以使用简单的列表理解或映射将一个类的列表转换为另一个,例如:

>>> l = [A('Greg', 33), A('John', 39)]
>>> l
[A('Greg', 33), A('John', 39)]

>>> map(B.from_A, l)  # will look different, but is more memory-efficient, in 3.x
[B('Greg', 33), B('John', 39)]

>>> [B.from_A(a) for a in l]  # works (nearly) identically in 2.x and 3.x
[B('Greg', 33), B('John', 39)]

不仅在Python中,而且在大多数基于OO的语言中,只编写数据对象都是不受欢迎的。可能最具python风格的方式是传递平面数据,比如一个dict或dict列表:

{'Greg': 33, 'John': 39}

[{'name': 'Greg', 'age': 33}, {'name': 'John', 'age': 39}]
也就是说,假设您有类A和B,并且希望从现有A实例实例化新的B:

class A(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return '<{cls} name={s.name}, age={s.age}>'.format(
            cls=self.__class__.__name__,
            s=self
        )

class B(A):
    def __init__(self, name, age, born_as='male'):
        super(B, self).__init__(name, age)
        self.born_as = born_as

data = {'Greg': 33, 'John': 39}
list_of_a = [A(k, v) for k, v in data.items()]
由于B现在知道如何克隆A:

>>> [B.clone(a) for a in list_of_a]
[<B name=Greg, age=33>, <B name=John, age=39>]        
为所有类B类编写克隆方法可能会变得单调乏味。内省是非常有益的,所以我们不要重复我们自己:

class CloneFromInstanceMixin(object):
    @classmethod
    def clone(cls, instance, **kwargs):
        constructor_args = inspect.getargspec(instance.__init__).args
        for attr_name in constructor_args:
            if attr_name in kwargs:
                continue # overrides instance attribute
            try:
                kwargs[attr_name] = getattr(instance, attr_name)
            except AttributeError:
                pass
        return cls(**kwargs)

class B(CloneFromInstanceMixin, A):
    def __init__(self, name, age, born_as='male'):
        super(B, self).__init__(name, age)
        self.born_as = born_as

>>> [B.clone(a) for a in list_of_a]
[<B name=Greg, age=33>, <B name=John, age=39>]   

我可能有太多的空闲时间。

你能从B上的类方法定义a吗?那么它就是l2=mapB.from_A,l,或者[B.from_Ainst for inst in l]。如果A是一个映射,你甚至可以做一些聪明的事情,比如[B**inst for inst in l]。可能是一个列表理解:[Ba.name,A.age for A in list_of A]注意,我已经删除了对复杂类型的引用,因为我可能不是唯一一个立即想到1+2j…@jornsharpe的人,我喜欢你的from_A想法,而不是在列表中列出构造函数的所有参数。但有一个问题,那就是Pythonic,你能给我指一下任何支持或反对Pythonic的文档或文章吗?@GregB我不知道Pythonic的具体情况,我手头也没有任何参考资料,但是,在Python中,使用类方法作为替代构造函数(例如from_string)是非常常见的,保持类的职责定义良好且自包含是OOP的基础。好的,到目前为止,我很喜欢它,从我所读到的关于Pythonicness的内容来看,它似乎非常Pythonic。我会花一点时间看看是否还有其他人,但到目前为止,你已经赢了。我不同意你关于仅数据对象的第一点。你熟悉这种气味吗?也许你是对的,但是在像Python这样的动态语言中,如果你不打算将一些方法与数据结合起来,我看不出定义类的意义。对比:顺便说一句,《原始痴迷气味》中提出的解决方案明确鼓励您将方法与数据结合起来,看看它们关于吸引人的代码的观点。当然,值得注意的是,我的类型A和B是人为的,纯粹是为了示例代码的目的。感谢mixin示例。看到这种工作方式很有趣。
>>> [B.clone(a) for a in list_of_a]
[<B name=Greg, age=33>, <B name=John, age=39>]        
class CloneFromInstanceMixin(object):
    @classmethod
    def clone(cls, instance, **kwargs):
        constructor_args = inspect.getargspec(instance.__init__).args
        for attr_name in constructor_args:
            if attr_name in kwargs:
                continue # overrides instance attribute
            try:
                kwargs[attr_name] = getattr(instance, attr_name)
            except AttributeError:
                pass
        return cls(**kwargs)

class B(CloneFromInstanceMixin, A):
    def __init__(self, name, age, born_as='male'):
        super(B, self).__init__(name, age)
        self.born_as = born_as

>>> [B.clone(a) for a in list_of_a]
[<B name=Greg, age=33>, <B name=John, age=39>]