![](/img/trans.png)
[英]What is the most pythonic way to map two different strings, to act as one?
[英]What is the Pythonic way to map a sequence of one custom class to another?
(...或者,C#的Select(...)
方法的Python版本是什么?)
給定一個列表l
的自定義類的A
是什么(最?)Python的到的每一個元素映射方式l
,以不同的自定義類B
?
例如,以下代碼可以做到這一點,但這是最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()
擴展方法從源序列投影到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)
然后,您可以使用簡單的列表理解甚至map
將一個類的列表轉換為另一個類,例如:
>>> 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化的方式是傳遞一個平面數據或一系列字典:
{'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()]
您可以使其簡單明了:
>>> list_of_a
[<A name=Greg, age=33>, <A name=John, age=39>]
>>> [B(a.name, a.age) for a in list_of_a]
[<B name=Greg, age=33>, <B name=John, age=39>]
如果涉及很多屬性,則可能會有些冗長。 讓我們教B如何克隆A:
class B(A):
def __init__(self, name, age, born_as='male'):
super(B, self).__init__(name, age)
self.born_as = born_as
@classmethod
def clone(cls, instance, *args, **kwargs):
return cls(instance.name, instance.age, *args, **kwargs)
由於B現在知道如何克隆A:
>>> [B.clone(a) for a in list_of_a]
[<B name=Greg, age=33>, <B name=John, age=39>]
為所有類似B的類編寫克隆方法可能很麻煩。 內省是Python風格的,所以不要重復自己:
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>]
我可能有太多的空閑時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.