3

I have created a class distance_neighbor in which one of the attributes is a list of objects of class Crime.
That is the value for all attributes I get from database query result.

At first, I have set data_Crime list as the value for attribute **Crime on class distance_neighbor, and I used del to clear data_Crime list after used, so that the data_Crime list can used in the next loop.

This is my code:

conn = psycopg2.connect("dbname='Chicago_crime' user='postgres'  host='localhost' password='1234'")
cur= conn.cursor()

minDistance=float(input("Nilai minimum distance : "))
cur.execute("""SELECT id_objek1, objek1, id_objek2, objek2, distance from tb_distance1 where distance<'%f'""" %(minDistance))

class Crime:
   def __init__(self, id_jenis, jenis):
      self.id_jenis=id_jenis
      self.jenis=jenis

class distance_neighbor (Crime):
   def __init__(self, distance, **Crime):
      self.distance = distance
      self.Crime = Crime

data_Crime =[]
data_distance = []

for id_objek1, objek1, id_objek2, objek2, distance in cur.fetchall():
    data_Crime.append(Crime(id_objek1,objek1))
    data_Crime.append(Crime(id_objek2,objek2))
    data_distance.append(distance_neighbor(distance, data_Crime))
    del data_Crime[:]

error Message:

data_distance.append(distance_neighbor(distance, data_Crime))   
TypeError: __init__() takes exactly 2 arguments (3 given)

I have fixed my code using below answers guys, Thank you

0

3 Answers 3

1

This should be closer to what you want:

class Crime(object):
    def __init__(self, id_jenis, jenis):
        self.id_jenis=id_jenis
        self.jenis=jenis

class DistanceNeighbor(object):
    def __init__(self, distance, crimes):
        self.distance = distance
        self.crimes = crimes


data_distance = []
for id_objek1, objek1, id_objek2, objek2, distance in cur.fetchall():
    crimes = [Crime(id_objek1,objek1), Crime(id_objek2,objek2)]
    data_distance.append(DistanceNeighbor(distance, crimes))

Classes in Python 2 should always inherit from object. By convention, class names are in CamelCase.

The inheritance of DistanceNeighbor from Crime seems unnecessary. I changed this.

Attributes to instance should be lower case, therefore I used crimes instead of the very confusing reuse of the class name Crime.

This line:

def __init__(self, distance, **Crime):

takes your list of Crime instance apart as separate arguments. In your case it means the __init__ receives:

distance, data_Crime[0], data_Crime[0]

this causes this error message:

TypeError: init() takes exactly 2 arguments (3 given)

The instantiation of Crime is pretty short. So, instead of the two appends you can create the list of the two Crime instances in one line:

crimes = [Crime(id_objek1,objek1), Crime(id_objek2,objek2)]

Since this creates a new list in each loop, there is no need to delete the list content in each loop, as you did with del data_Crime[:].

Sign up to request clarification or add additional context in comments.

Comments

1

You've defined your __init__ method in distance_neighbor as taking arguments (self, distance, **Crime). The ** before Crime tells Python to pack up any keyword arguments you're passed into a dictionary named Crime. That's not what you're doing though. Your call is distance_neighbor(distance, data_Crime) where data_Crime is a list. You should just accept that as a normal argument in the __init__ method:

class distance_neighbor (Crime):
   def __init__(self, distance, crime):
      self.distance = distance
      self.crime = crime

This will mostly work, but you'll still have an issue. The problem is that the loop that's creating the distance_neighbor objects is reusing the same list for all of them (and using del data_Crime[:] to clear the values in between). If you are keeping a reference to the same list in the objects, they'll all end up with references to that same list (which will be empty) at the end of the loop.

Instead, you should create a new list for each iteration of your loop:

for id_objek1, objek1, id_objek2, objek2, distance in cur.fetchall():
    data_Crime = [Crime(id_objek1,objek1), Crime(id_objek2,objek2)]
    data_distance.append(distance_neighbor(distance, data_Crime))

This will work, but there are still more things that you probably want to improve in your code. To start with, distance_neighbor is defined as inheriting from Crime, but that doesn't seem appropiate since it contains instance of Crime, rather than being one itself. It should probably inherit from object (or nothing if you're in Python 3 where object is the default base). You may also want to change your class and variable names to match Python convention: CamelCase for class names and lower_case_with_underscores for functions, variables and attributes.

Comments

0
def __init__(self, distance, **Crime):

**Crime is a keyword argument, and expects named arguments. You don't need that, remove the asterisks.

Also, rename the argument, it's very confusing that it has the same name as the class:

class distance_neighbor(Crime):
   def __init__(self, distance, c):
      self.distance = distance
      self.Crime = c

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.