假设我有一个程序可以创建一些带有线和点的方案。 所有行都由两点确定。有这些课程:
class Coordinates(object):
def __init__(self, x, y):
self.x = x
self.y = y
class Point(object):
def __init__(self, coordinates):
self.coordinates = coordinates
class Line(object):
def __init__(self, coordinates_1, coordinates_2):
self.coordinates_1 = coordinates_1
self.coordinates_2 = coordinates_2
一个方案采用行列表并创建一个唯一点列表。
class Circuit(object):
def __init__(self, element_list):
self.line_list = element_list
self.point_collection = set()
self.point_collection = self.generate_points()
def generate_points(self):
for line in self.line_list:
coordinates_pair = [line.coordinates_1, line.coordinates_2]
for coordinates in coordinates_pair:
self.point_collection.add(Point(coordinates))
return self.point_collection
哪些变体能够制作独特对象的列表或集合?如何在不使用集合和排序的情况下执行此操作,仅使用循环和条件?如何做到更简单?
UPD。我附上的代码不能正常工作。我尝试在Point类中添加哈希和 eq 方法:
class Point(object):
def __init__(self, coordinates):
self.coordinates = coordinates
def __hash__(self):
return 0
def __eq__(self, other):
return True
然后我尝试用一些行来制定一个方案:
element_list=[]
element_list.append(Line(Coordinates(0,0), Coordinates(10,0)))
element_list.append(Line(Coordinates(10,0), Coordinates(10,20)))
circuit = Circuit(element_list)
print(circuit.point_collection)
这里的两条线等于四个点,其中两个点具有相同的坐标。因此,代码必须打印三个对象,但它只有一个:
{<__main__.Point object at 0x0083E050>}
答案 0 :(得分:2)
简答:
您需要在__hash__()
课程中实施__eq__()
和Point
方法。
有关想法,请参阅此answer showing a correct and good way to implement __hash__()
。
答案很长:
set对象是不同的hashable对象的无序集合。常见用途包括(...)从序列(...)
中删除重复项
如果对象具有在其生命周期内永远不会更改的哈希值(它需要
__hash__()
方法),并且可以与其他对象进行比较(它需要__eq__()
方法),则该对象是可清除的。比较相等的Hashable对象必须具有相同的哈希值。默认情况下,作为用户定义类实例的对象是可清除的;它们都比较不相等(除了它们自己),它们的哈希值来自它们的
id()
。
这解释了为什么您的代码不会删除重复点。
考虑这个实现,它使Foo
的所有实例都不同,Bar
的所有实例都相等:
class Foo:
pass
class Bar:
def __hash__(self):
return 0
def __eq__(self, other):
return True
现在运行:
>>> set([Foo(), Foo()])
{<__main__.Foo at 0x7fb140791da0>, <__main__.Foo at 0x7fb140791f60>}
>>> set([Bar(), Bar()])
{<__main__.Bar at 0x7fb1407c5780>}
在您的情况下,__eq__
应该在两个坐标相等时返回True
,而__hash__
应该返回坐标对的哈希值。请参阅前面提到的答案,以获得这样做的好方法。
一些评论:
从设计的角度来看,您的Point
班级目前no reason to exist,因为它只是Coordinates
的包装,不提供其他功能。您应该只使用其中一个,例如:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
为什么不调用coordinates_1
和coordinates_2
a
和b
?
class Line(object):
def __init__(self, a, b):
self.a = a
self.b = b
此外,您的generate_points
可以更加pythonic的方式实现:
def generate_points(self):
return set(p for l in self.line_list for p in (l.a, l.b))
最后,为了便于调试,您的班级可能会consider implementing __repr__
and __str__
methods。