3 svar
92 visningar
Kemibiologi1999 behöver inte mer hjälp
Kemibiologi1999 43
Postad: 4 dec 2021 18:39

Overrida __contains__ så att jag får True

Jag har skapat en subklass vid namnet Point och en superklass vid namnet Triangel. Klassen Point har tre attribut som är: punkt1, punkt2 och punkt 3. Triangeln har tre egna attribut som jag döpt till P1, P2 och P3 och utgörs av objekt skapade av typen Punkt.

    p1 = Point(1, 1, 1)
    p2 = Point(2, 2, 2)
    p3 = Point(3, 3, 3)
    triangles = [
        Triangle(p1, p2, p3),
        Triangle(p1, p3, p2),
        Triangle(p2, p1, p3),
        Triangle(p2, p3, p1)
    ]

    # Try to find triangle in list
    print(Triangle(p1, p2, p3) in triangles)
    print(Triangle(p3, p1, p2) not in triangles)

 

Jag vill att följande skall ge mig True i båda fallen, men får enbart True på det sista fallet. Jag har sökt på google och sett att jag behöver overrida __contains__. Försökte med

 

    def __contains__(self, other):
        x = False
        if self.Triangle in other.Triangle:
            x = True
        return x

till ingen nytta.

Någon som kan hjälpa mig?

Laguna Online 30484
Postad: 4 dec 2021 20:09

Jag behöver nog se hela koden för att förstå.

Kemibiologi1999 43
Postad: 4 dec 2021 22:22
from Point import Point
import math
# A class for a Triangle in 3D - should use Point class and Heron's formula
# NOTE: No IO here, this is just the logical concept.
# To test, run Ex2TestPointTriangle
class Triangle:
    def __init__(self, P1: Point, P2: Point, P3: Point):
        self.P1 = P1 #P1 är då en point med tre punkter
        self.P2 = P2
        self.P3 = P3


    def area(self): #calculate distance between the three points
        d1 = self.P1.distance(self.P2)
        d2 = self.P2.distance(self.P3)
        d3 = self.P3.distance(self.P1)
        s = d1 + d2 + d3
        s = s/2
        a = math.sqrt(s *(s-d1) * (s-d2) * (s-d3))
        return a

    def __contains__(self, other):
        x = False
        if self.Triangle in other.Triangle:
            x = True
        return x
# package exercises.ex2usemoreclasses
import math
from multipledispatch import dispatch
# A class for points in 3D. Should be considered immutable, no mutating methods
# NOTE: No IO here, this is just the logical concept.
# To test, run Ex2TestPointTriangle
class Point:
    def __init__(self, *args):
        if len(args) == 3:
            self.point1 = args[0]
            self.point2 = args[1]
            self.point3 = args[2]
        elif len(args) == 1:
            self.copy(args[0])
        else:
            raise ValueError("Wrong value.")


    def distance(self, other):
        point1_difference = self.point1 - other.point1
        point2_difference = self.point2 - other.point2
        point3_difference = self.point3 - other.point3

        distance = math.sqrt(math.pow(point1_difference, 2) + math.pow(point2_difference, 2) + math.pow(point3_difference, 2))
        return distance



    def copy(self, other):
        self.point1 = other.point1
        self.point2 = other.point2
        self.point3 = other.point3
# package exercises.ex2usemoreclasses

from Point import Point
from Triangle import Triangle
#  This is a test of Classes (objects of) Point and Triangle
#
#  See
#  - usemoreclasses
def test_point_triangle():
    # All should print true as usual
    
    # Point
    p = Point(1, 2, 3)
    d = Point(1,2,3)
    print(p.distance(d))
    print(p.distance(Point(p)) == 0)
    print(Point(0, 0, 0).distance(Point(1, 0, 0)) == 1)

    # Triangle uses Points!
    t = Triangle(Point(0, 0, 0), Point(0, 1, 0), Point(1, 0, 0))
    print(abs(t.area() - 0.5) < 0.000001)  # Area should be 0.5

    # Test data
    p1 = Point(1, 1, 1)
    p2 = Point(2, 2, 2)
    p3 = Point(3, 3, 3)
    triangles = [
        Triangle(p1, p2, p3),
        Triangle(p1, p3, p2),
        Triangle(p2, p1, p3),
        Triangle(p2, p3, p1)
    ]

    # Try to find triangle in list
    print(Triangle(p1, p2, p3) in triangles)
    print(Triangle(p3, p1, p2) not in triangles)


if __name__ == "__main__":

 

Den är lite lång, men det är tre olika klasser som du ser.  Jag försökte skriva över __contains__ som du ser, för att anpassa den för detta scenario, men misslyckades. Koden beter sig annars som den bör på resten av grejerna

CurtJ 1201
Postad: 5 dec 2021 00:49

I print(Triangle(p1, p2, p3) in triangles) kontrollerar du om en nyskapad Triangle finns i listan triangles. Det är två fel: För det första så är triangeln nyskapad (Triangle(p1, p2, p3) är ett nytt objekt) och därmed kan det aldrig finnas i listan. För det andra så är triangles en Python-lista och den klassen implementerar en __contains__ som kontrollerar identiteten på objektet.

Ex

t1 = Triangle(p1,p2,p3)
triangles.append(t1)
t1 in triangles # är sant
Triangle(p1,p2,p3) in triangles # är falskt

Om du vill kontrollera om en triangel mellan tre punkter finns i listan triangles så kan du göra på två sätt

a) Ärv pythons list-objekt till en ny klass och ersätt (override) metoden __contains__. I den kontrollerar du om listan innehåller en triangel med de tre punkterna.

class MyList(list):

	def __init__(self,arg):
		super(list, self).__init__()
		self.arg = arg

	def __contains__(this, other):
		# Loopa igeenom elementen i den här listan
		for x in this:
			# Kontrollera om elementen är lika (inte samma) 
			# Förutsätter att elementets klass (Triangle) 
			# implementerar __eq__
			if x == other:
				return True
		return False

b) Skapa en egen klass som implementerar en lista och innehåller en __contains__ som gör samma sak som ovan.

Vilket du väljer är en smaksak.

 

Notera att när du kontrollerar om de tre punktera är de samma så måste du kontrollera innehållet i punkten, inte punktens identitet. Du kan alltså  inte kontrollera enklass.p1 == enannanklass.p1 för den kontrollerar att p1 i de båda instanserna pekar på samma objekt och det vill du nog inte i allmänhet. Du kan uppnå det med att implementera metoden __eq__som kontrollerar innehållet i punkterna snarare än deras identitet..

ex:

def __eq__ (self, p):
        return p.point1==self.point1 and p.point2==self.point2 and p.point3==self.point3

 

Det här borde leda dig vidare men återkom hit annars så får du mer hjälp

Svara
Close