I have re-done it a few times but I can't get it to work... It detects collisions when button1 is in the lower and/or right-most part of button2, but not if it's in the upper and/or left-most part... Would be nice to know what the problem is cuz I suck at debugging...

```
if (
    (
        (button1.Top >= button2.Top && button1.Top <= (button2.Top + button2.Height)) 
        || (button1.Bottom >= button2.Bottom && button1.Bottom <= (button2.Bottom + button2.Height))
    ) 
    && 
    (
        (button1.Left >= button2.Left && button1.Left <= (button2.Left + button2.Width)) 
        || (button1.Right >= button2.Right && button1.Right <= (button2.Right + button2.Width))
    )
)

```
['https://Stackoverflow.com/questions/34365395', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/5696900/']
In general, I think that question is more suited for Code Review not Stack Overflow.

Maybe you should rethink your class completely. For me it looks a lot like you wanted to model the student and not the classroom. Something like following might fit your needs better: 

```
class Student(object):
    """A class to model students"""

    def __init__(self, age, grade, name):
        self.age = age
        self.grade = grade
        self.name = name

    def get_all_information(self):
        """Get all information about the student"""
        return (self.age, self.grade, self.name)

james = Student(15, 9, 'James Herbert')
print(james.get_all_information())

```

**Edit:**
It seems others like [Prune](https://stackoverflow.com/users/4785185/prune) came up with the same idea.
Your problem boils down to a fundamental misunderstanding about how classes work. A class is just a template (think of a cookie cutter shape). By calling the class you are creating an instance of the class. An instance is to a class what a cookie is to a cookie cutter. The function that tells your class how to make an instance is the `__init__` function. So when you call:

```
x = Classroom()

```

What happens is the `__init__` function is called for `Classroom`. You may be asking "But I didn't ever write an `__init__` function for the class, so how does that work?" Simply put, *all classes in python will automatically inherit from the `object` class even if they don't explicitly code it in*, which means they use its methods unless you explicitly override them with your own. `object` has a very simple `__init__` that pretty much doesn't do anything.

Going back to the cookie cutter analogy, in the same way that you can make different flavors of cookie (e.g. chocolate chip, oatmeal, peanut butter) from the same cookie cutter, so too can classes make different instances when you instantiate them with different parameters. Like so (adapted from @Prune's answer):

```
class Student(object):
    def __init__(self, name, age, grade):
        self.name = name
        self.age = age
        self.grade = grade

    def print_student(self):
        print (self.age, self.grade, self.name)

James = Student('James Herbert', 15, 9)
James.print_student()

Diego = Student('Diego Heriberto', 14, 9)
Diego.print_student()

```

Which should print out:

```
15 9 James Herbert
14 9 Diego Heriberto

```

Each instance is different, and so behaves differently, but they both follow the same template laid out by the class.

If you want a `Classroom` class, you could do something like this:

```
class Classroom(object):
    def __init__(self):
        # create a list to hold students and assign the list to self
        self.students = list()

    def add_student(self, student):
        self.students.append(student)

    def print_students(self):
        # use a loop to print out all the students in the classroom instance
        for stud in self.students:
            stud.print_student()

cr = Classroom()
James = Student('James Herbert', 15, 9)
Diego = Student('Diego Heriberto', 14, 9)

cr.add_student(James)
cr.add_student(Diego)

cr.print_students()

```

This would have identical output to what was shown previously.

You may ask yourself "But there is the 'self' parameter that I never pass in. Is Python broken?" Python is working just fine. The `self` parameter is implicit when you call a method on an instance like `James` or `Diego`, but it is explicit in the actual body of the method. If you want to modify the instance in a method, then you must modify the `self` parameter. That is why we assign values to it in `__init__`. If you want to find out something about an instance, you check for it on the `self` parameter.