Kacper
Kacper

Reputation: 104

If python is making a copy of an object, how to stop it?

I am coding a program to find the best week schedule of driving classes,
"jazda" - Polish for driving lesson (singular).
"jazdy" - means "driving lessons" (plural).

I have class Student and class Jazda
after appending Student object and creating him an atribute it no longer exists on different reference.
This is how i store schedule data
self.dict_schedule = { "monday":[ < Jazda7-9>, < Jazda9-11>, < Jazda12-14>],
"tuesday":[ < Jazda8-10>, < Jazda10-12>, < Jazda13-15>] ...
"friday": ... }

This is class method

def min_jazdy_made(self):
    list_of_students = []

    # Counting how many jazdy is in schedule
    for day, jazdy in self.dict_schedule.items():
        for jazda in jazdy:
            if jazda.student in list_of_students:
                DEBUG(debugging, ("id student", id(jazda.student), "student", list_of_students[-1]) )
                #jazda.student.jazdy += 1                                          <--- this doesnt work, it creates error
                list_of_students[list_of_students.index(jazda.student)].jazdy += 1 <--- this works (2)
            else:
                list_of_students.append(jazda.student) <--- is here the copy being made?
                list_of_students[-1].jazdy = 1         <--- i am creating atribute
                DEBUG(debugging, ("id student", id(list_of_students[-1]), "student", list_of_students[-1]) )

    # Checking if it meets requirements
    for student in self.students_ls:
        if student in list_of_students:
            if not student.jazdy >= student.min_jazdy:  <--- if I use (2) error comes in here
                return False, student
        else:
            if student.min_jazdy > 0:
                return False, student

    return True, None

Output:


new_models.py:225 min_jazdy_made | id student 54223632 student <J.D. Student nr 0>
new_models.py:218 min_jazdy_made | id student 54223752 student <J.D. Student nr 0>
new_models.py:218 min_jazdy_made | id student 54223872 student <J.D. Student nr 0>
new_models.py:225 min_jazdy_made | id student 54223992 student <J.D. Student nr 1>
new_models.py:225 min_jazdy_made | id student 54224112 student <J.D. Student nr 7>
new_models.py:225 min_jazdy_made | id student 54224232 student <J.D. Student nr 5>
new_models.py:225 min_jazdy_made | id student 54224352 student <J.D. Student nr 2>
new_models.py:218 min_jazdy_made | id student 54224472 student <J.D. Student nr 2>
new_models.py:218 min_jazdy_made | id student 54224592 student <J.D. Student nr 2>
new_models.py:225 min_jazdy_made | id student 54224712 student <J.D. Student nr 6>
new_models.py:218 min_jazdy_made | id student 54224832 student <J.D. Student nr 6>
new_models.py:218 min_jazdy_made | id student 54224952 student <J.D. Student nr 6>
new_models.py:218 min_jazdy_made | id student 54225072 student <J.D. Student nr 6>
new_models.py:218 min_jazdy_made | id student 54225192 student <J.D. Student nr 6>
new_models.py:218 min_jazdy_made | id student 54225312 student <J.D. Student nr 6>
new_models.py:218 min_jazdy_made | id student 54225432 student <J.D. Student nr 6>
new_models.py:218 min_jazdy_made | id student 20768224 student <J.D. Student nr 6>
Traceback (most recent call last):
  File "Code\Python\projects\generator_rozkladow\rozklady_jazd\main_gen.py", line 52, in <module>
    full_sched = sched.recursive_schedule_maker(level=0)
  File "C:\Users\Admin\Code\Python\projects\generator_rozkladow\rozklady_jazd\new_models.py", line 511, in recursive_schedule_maker
    ret = self.recursive_schedule_maker( **kwargs)
  File "C:\Users\Admin\Code\Python\projects\generator_rozkladow\rozklady_jazd\new_models.py", line 511, in recursive_schedule_maker
    ret = self.recursive_schedule_maker( **kwargs)
  File "C:\Users\Admin\Code\Python\projects\generator_rozkladow\rozklady_jazd\new_models.py", line 511, in recursive_schedule_maker
    ret = self.recursive_schedule_maker( **kwargs)
  [Previous line repeated 15 more times]
  File "C:\Users\Admin\Code\Python\projects\generator_rozkladow\rozklady_jazd\new_models.py", line 455, in recursive_schedule_maker
    if schedule_out.evaluate_self()!=False:
  File "C:\Users\Admin\Code\Python\projects\generator_rozkladow\rozklady_jazd\new_models.py", line 254, in evaluate_self
    BOOL, student = self.min_jazdy_made()
  File "C:\Users\Admin\Code\Python\projects\generator_rozkladow\rozklady_jazd\new_models.py", line 229, in min_jazdy_made
    if not student.jazdy >= student.min_jazdy:
AttributeError: 'Student' object has no attribute 'jazdy'

I want to access .jazdy atribuute from object that would be appended to list and from an object that came in jazda.student.jazda,

How do I do that?

Upvotes: 0

Views: 39

Answers (1)

alani
alani

Reputation: 13079

There is nothing in your code that would create any copies of Student objects, only references to them.

Here is what I suspect is happening:

  • your input (in self.dict_schedule) already contains multiple instances of each student (e.g. "J.D. Student nr 0") for some reason

  • you have code in a comparison method (Student.__eq__) which means that these copies are being treated as being equal

  • the if jazda.student in list_of_students is finding not the exact object pointed to by jazda.student, but another one on the list which is equal to it

  • therefore the jazda.student.jadzy is not being initialised because list_of_students[list_of_students.index(jazda.student)] is pointing to a different object from jazda.student

The behaviour of in (and index) in relation to objects which are distinct but equal can be seen by this example:

>>> lst = [10, 20]

>>> 20.0 in lst
True

>>> lst.index(20.0)
1

>>> 20.0 is 20
False

>>> 20.0 == 20
True

Upvotes: 1

Related Questions