处理单个元素或序列的泛型函数



我想要一个能够处理序列和单个元素参数的泛型函数get_me()

代码如下:

from typing import Sequence
class class_1:
def __init__(self, i: int=0):
self.name = 'A'+str(i)
def __repr__(self):
return self.name
class class_2:
def __init__(self, i: int=0):
self.name = 'B'+str(i)
def __repr__(self):
return self.name
def get_me(seq: Sequence):
for s in seq:
print(f"n1 is {s[0].name}, 2 is {s[1].name}")

这适用于以下所有组合:

one = class_1(1), class_2(1)
two = class_1(2), class_2(2)
three = class_1(3), class_2(3)
many = [one, two, three]
many = (one, two, three)
many = {one, two}
many = one, two
get_me(many)

但给出的CCD_ 2

get_me(一个(

有可能让这个代码在没有try: except的情况下处理它吗?

也许这就是你想要的:

from typing import Sequence, Union, Tuple
# ...
def get_me(seq: Union[Sequence, Tuple]):
if isinstance(seq, tuple):
seq = (seq,)
for s in seq:
print(f"n1 is {s[0].name}, 2 is {s[1].name}")

这依赖于单个元素是元组,就像您的示例中一样,但print语句也是如此,所以这似乎是合理的。如果您需要它来工作于任何类型,您可以将其替换为Any,并检查它是否不是序列——但当然,您还必须修改print语句,以及使用该参数的任何其他代码。

您注意到,当您将many定义为:时,此解决方案不起作用

many = one, two

这是正确的,因为这也使得许多Tuple

为了支持这一点,你需要这样的东西:

def get_me(seq: Sequence):
if not isinstance(seq[0], tuple):
seq = (seq,)
for s in seq:
print(f"n1 is {s[0].name}, 2 is {s[1].name}")

然而,这并没有那么严格或明确。另一种方法是:

class SuperClass:
pass

class Class1(SuperClass):
# ...

class Class2(SuperClass):
# ...

# ... 

def get_me(seq: Union[Sequence[SuperClass], SuperClass]):
if isinstance(seq, SuperClass):
seq = (seq,)
for s in seq:
print(f"n1 is {s[0].name}, 2 is {s[1].name}")

如果所有的显式类型都是必需的,那么这是我更喜欢的解决方案。

由于参数类型的各种可能排列,在保持代码简单的同时,似乎无法避免try: except

所以代码。。。

def get_me(seq: Sequence):
try:
for s in seq:
print(f"n1 is {s[0].name}, 2 is {s[1].name}")
except (TypeError, AttributeError):
print(f"n1 is {seq[0].name}, 2 is {seq[1].name}")

适用于我所有可能的情况:

one = class_1(1), class_2(1)
two = class_1(2), class_2(2)
three = class_1(3), class_2(3)
many = [one, two, three]
many = (one, two, three)
many = {one, two}
many = one, two
get_me(many)
get_me(one)
get_me(two)
get_me(three)

最新更新