1

I am making a game which requires many x, y, and z coordinates and they all have a function to themselves. I need to use the x or y function inside another function to make it run through that function. I am not trying to def the function inside it, but only to put if in front of it and make that code run. They are both in the same class but different indentations.

Can some tell me why I can't rerun that code inside another function without getting an unresolved reference.


Here is a snippet of my code.

def within_y(co1,co2):
    if (co1.y1 > co2.y1 and co1.y1 < co2.y2) \
        or (co1.y2 > co2.y1 and co1.y2 < co2.y2) \
        or (co2.y1 > co1.y1 and co2.y1 < co1.y2) \
        or (co2.y2 > co1.y1 and co2.y2 < co1.y1):
        return True
    else:
         return False

def collided_left(co1, co2):
    if within_y(co1, co2):
         if co1.x1 <= co2.x2 and co1.x1 >= co2.x1:
             return True
    return False

In this case, the if within_y(co1, co2): returns the error

Thank you guys, I am still learning syntax and basic python.

Here is my new code.

class Coords:
    def __init__(self, x1=0,y1=0, x2=0, y2=0):
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2

    def within_x(co1, co2):
        if (co1.x1 > co2.x1 and co1.x1 < co2.x2) \
            or (co1.x2 > co2.x1 and co1.x2 < co2.x2) \
            or (co2.x1 > co1.x1 and co2.x1 < co1.x2):
            return True
        else:
            return False

    def within_y(co1,co2):
        if (co1.y1 > co2.y1 and co1.y1 < co2.y2) \
            or (co1.y2 > co2.y1 and co1.y2 < co2.y2) \
            or (co2.y1 > co1.y1 and co2.y1 < co1.y2) \
            or (co2.y2 > co1.y1 and co2.y2 < co1.y1):
            return True
        else:
            return False

    def collided_left(co1, co2):
        if within_y(co1, co2):
            if co1.x1 <= co2.x2 and co1.x1 >= co2.x1:
                return True
        return False

    def collided_right(co1, co2):
        if within_y(co1, co2):
            if co1.x2 >= co2.x1 and co1.x2 <= co2.x2:
                return True
        return False

    def collided_top(co1, co2):
        if within_y(co1,co2):
            if co1.y1 <= co2.y2 and co1.y1 >= co2.y1:
            return True
        return False

    def collided_bottom(y, co1, co2):
        if within_x(co1, co2):
            y_calc = co1.y2 + y
            if y_calc >= co2.y1 and y_calc <= co2.y2:
                return True
        return False

I have another class that does all the visuals and is unneeded in this question.

I also forgot to say that this is a stickman game where you need to jump the stickman around some platforms to get to a door.

8
  • 4
    "They are both in the same class" - why are these in a class? They don't look like methods. Commented Apr 18, 2016 at 22:48
  • This code sample runs fine on its own. There's probably something surrounding it causing this. Mind posting the whole class? Commented Apr 18, 2016 at 22:51
  • 1
    Could you please post your full code? Commented Apr 18, 2016 at 22:51
  • The indentation is a little messed up. Did you accidentally indent collided_left by one space, as it is in your posted code? If so, then calling it outside of within_y will fail. Commented Apr 18, 2016 at 22:57
  • 1
    When getting errors in your Python code, please post the full traceback. Commented Apr 18, 2016 at 23:17

2 Answers 2

2

This is a scope issue. When you define a function inside a class, it's not accessible by its name from other functions defined within the class. Rather, you need to access it via the class name (or an instance of the class) and get the function as an attribute.

Changing your calls to within_y to Coords.within_y should work. But I'm not sure that easy fix is really the best fix.

When you define a function in a class, usually it's intended to be a method, called on an instance of the class. For instance:

class Foo():
    def bar(self):
        print("bar")

    def quux(self):
        print("quux")
        self.bar()
        print("quuux")

f = Foo()
f.bar() # prints bar
f.quux() # prints quux, then bar, then quuux, each on its own line

Since your within_y and various collided_X functions look like they take a Coords instance as their first argument, you can already use them as methods. So rather than Coords.within_y(co1, co2), you could call co1.within_y(co2). So that's an alternative way to fix your code, with minimal changes.

However, it would be a bit more natural looking (for Python code) if you changed the parameter names so that co1 was self and co2 was something else (like other, perhaps). Naming the first argument of a method self is a convention, so you don't always need to follow it, but doing so will make your code much easier to understand for anyone else who reads it. Anyone who sees def foo(self) will know right away that they're reading a method, and self is the instance the method is being called on.

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

1 Comment

I forgot all about how you can do Coords.witin_y! Sometimes I might need a refresher about playing around with the classes and functions...
0

You can put a function inside another function — which makes it a local function that can only be called immediately inside the outer function — if you indent it properly. You can also just return the value of logical expressions directly rather than writing things like:

if logical_expression:
    return True
else:
    return False

Lastly, in Python long lines can often be split-up by enclosing expressions (or sub-expressions) in parentheses, which often make them more readable and easier to extend or edit later.

Here's what your code might look like doing all these things:

def collided_left(co1, co2):
    def within_y(co1,co2):
        return ((co1.y1 > co2.y1 and co1.y1 < co2.y2) or
                (co1.y2 > co2.y1 and co1.y2 < co2.y2) or
                (co2.y1 > co1.y1 and co2.y1 < co1.y2) or
                (co2.y2 > co1.y1 and co2.y2 < co1.y1))

    return (within_y(co1, co2) and
            (co1.x1 <= co2.x2 and co1.x1 >= co2.x1))

2 Comments

I actually don't want to def another function or create one, but to reuse the within_y function that I already created.
To "reuse" the function in other scopes, it would have to have been defined in a common higher scope outside of both collided() and where ever else you want to use it.

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.