转化为;“收藏”;(list、set、single object等)放入Python中相同类型的新集合中
首先,我以非常一般的方式使用术语“容器”和“集合”,而不是与任何Python术语相关联 我在Python中有以下函数。它获取ID列表转化为;“收藏”;(list、set、single object等)放入Python中相同类型的新集合中,python,python-3.x,Python,Python 3.x,首先,我以非常一般的方式使用术语“容器”和“集合”,而不是与任何Python术语相关联 我在Python中有以下函数。它获取ID列表idlist,并返回与这些ID对应的objs对象列表。这很好: def findObj(idlist, objs): return [next(o for o in objs if id == o.id) for id in idlist] 问题是:idlist,返回值不一定必须是Python列表。我希望idlist也可以是一个普通id,并且函数将返回单个
idlist
,并返回与这些ID对应的objs
对象列表。这很好:
def findObj(idlist, objs):
return [next(o for o in objs if id == o.id) for id in idlist]
问题是:idlist
,返回值不一定必须是Python列表。我希望idlist
也可以是一个普通id,并且函数将返回单个对象。或者,idlist
将是一个Pythonset
,函数将返回对象的set
如何实现我可以为idlist
使用各种“容器”类型(包括普通id)并返回相同的“容器”类型?您可以将代码更改为:
import collections
def findObj(idlist, objs):
if isinstance(idlist, collections.Iterable):
return type(idlist)([next(o for o in objs if id == o.id) for id in idlist])
else:
#cover case when idlist is just plain object
pass
您可以将代码更改为:
import collections
def findObj(idlist, objs):
if isinstance(idlist, collections.Iterable):
return type(idlist)([next(o for o in objs if id == o.id) for id in idlist])
else:
#cover case when idlist is just plain object
pass
如果您的普通对象的id作为int(而不是string)传递(对于idliist),那么这应该可以工作
如果您的普通对象的id作为int(而不是string)传递(对于idliist),那么这应该可以工作
我认为你心目中的不是一个好的API。
让函数返回特定类型并让用户处理最终的转换更简单、更健壮、更不容易出错
特别是,我更喜欢使用生成器使函数变为惰性:
def find_obj(ids, objs):
try:
for id in ids:
yield next(o for o in objs if o.id == id)
except TypeError:
# ids not iterable? assume it is a plain id
yield next(o for o in objs if o.id == ids)
现在,用户只需执行以下操作:
list(find_obj(...))
set(find_obj(...))
next(find_obj(...)) # 1 element
得到他想要的东西
附加好处:
- 显式优于隐式:这里的类型转换是显式的。调用类型为find_obj(在别处定义的某些变量,对象)的图像代码现在,如果输入的定义不在附近,您如何知道将返回哪种类型
- 您可以传递类型
X
作为输入,并将其转换为类型Y
,而无需浪费中间空间和进行不必要的转换
- 不需要特殊情况。调用者可以提供一个不遵循通常的容器构造方法的输入(注意,没有标准的容器构造方法)
特殊情况下的备选方案单一身份证情况:
def find_obj(ids, objs):
try:
return (next(o for o in objs if o.id == id) for id in ids)
except TypeError:
for o in objs:
if o.id == id:
return o
当给定一系列id
时,上述函数返回一个生成器;当传入单个id
时,返回一个普通对象(而不是一个1元素生成器)
最后:大多数情况下(但不是总是),序列都有一个接受iterable的构造函数,并用这些元素构建容器。这意味着:
type(some_iterable)(something for el in some_iterable)
将生成一个与某些\u iterable
相同类型的容器
请注意,有些类需要一个列表
而不是泛型iterable,因此您必须使用类型(some_iterable)([使用中的抽象基类来查看对象是否是、a、a等。我认为您心目中的不是一个好的API。
让函数返回特定类型并让用户处理最终的转换更简单、更健壮、更不容易出错
特别是,我更喜欢使用生成器使函数变为惰性:
def find_obj(ids, objs):
try:
for id in ids:
yield next(o for o in objs if o.id == id)
except TypeError:
# ids not iterable? assume it is a plain id
yield next(o for o in objs if o.id == ids)
现在,用户只需执行以下操作:
list(find_obj(...))
set(find_obj(...))
next(find_obj(...)) # 1 element
得到他想要的东西
附加好处:
- 显式优于隐式:这里的类型转换是显式的。图像代码中调用的类型是
find\u obj(在别处定义的一些变量,对象)
现在,如果输入的定义不在附近,您如何知道将返回哪种类型
- 您可以传递类型
X
作为输入,并将其转换为类型Y
,而无需浪费中间空间和进行不必要的转换
- 不需要特殊情况。调用者可以提供不遵循通常的容器构造方法的输入(请注意,没有标准的容器构造方法)
特殊情况下的备选方案单一身份证情况:
def find_obj(ids, objs):
try:
return (next(o for o in objs if o.id == id) for id in ids)
except TypeError:
for o in objs:
if o.id == id:
return o
当给定一系列id
时,上述函数返回一个生成器;当传入单个id
时,返回一个普通对象(而不是一个1元素生成器)
最后:大多数情况下(但不总是序列)序列都有一个构造函数,该构造函数接受iterable并使用这些元素构建容器。这意味着:
type(some_iterable)(something for el in some_iterable)
将生成一个与某些\u iterable
相同类型的容器
请注意,有些类需要一个列表
而不是泛型iterable,因此您必须使用类型(some_iterable)([使用中的抽象基类来查看对象是否为、a、a等。返回类型(idlist)如何([下一步(objs中的o表示o,如果id==o.id)表示idlist中的id])?类型(idlist)
将为您提供传递给函数的对象的类型。现在您必须调用该类型构造函数[t=type(idlist);t(input_参数)
],并计算出所有的角点情况(如不是序列,而是对象等)。返回类型(idlist)如何(接下来(如果id=o,则在objs中为o)在idlist中为id),type(idlist)
将为您提供传递给函数的对象类型。现在您必须调用该类型构造函数[t=type(idlist);t(input_参数)
],并找出所有关键情况(如不是序列,而是对象等)。对实际上不是“异常”的对象使用异常是一个好主意吗?我不知道Python社区是怎么想的。对实际上不是“异常”的东西使用异常是一个好主意吗?我不知道Python社区是怎么想的。