1

I want to access object (specifically its variables) from functions defined in different file. Let's see an example:

File 1 - grail.py

import enemies

class Encounter:
    def __init__(self):
        self.counter = 1
        self.number = 0
        self.who = "We've encountered no one."

    def forward(self):
        if self.counter == 1:
            enemies.knightofni()
        elif self.counter == 2:
            enemies.frenchman()
        else:
            self.number = 42
            self.who = "We've found the Grail!"
        self.counter += 1

knight = Encounter()
for i in range(4):
    print(str(knight.number) + " " + knight.who)
    knight.forward()

File 2 - enemies.py (I probably need something in this file)

def knightofni():
    Object.number = 1
    Object.who = "We've encountered Knight of Ni."

def frenchman():
    Object.number = 4
    Object.who = "We've encountered French."

Output should show:

0 We've encountered no one.
1 We've encountered Knight of Ni.
4 We've encountered French.
42 We've found the Grail!

I know you can achieve the output by returning something from functions in file enemies.py, for example function frenchman() could look like:

def frenchman():
    return [4, "We've encountered French."]

and in grail.py I should change code to collect what the frenchman() returns:

...
        elif self.counter == 2:
            spam = enemies.frenchman()
            self.number = spam[0]
            self.who = spam[1]
...

but it uses additional resources, makes the code longer, and more cumbersome in more complicated situations.

Is there a way to do the job directly on the object's variables but keeping functions in separate file?

EDIT There are already answers to this question but maybe I will add clarification seeing doubt in one of the answers (citing comment to this answer):

I want it to be possible to add other "enemies" without making lengthy code in this place (so forward() is kind of a wrapper, place where it is decided what to do in different situations). It is also more readable if this functions are in different file.

Think of situation where there would be 100 "enemies" and each would need to change 100 variables which are lists with 1M entries each. Is there a better way than putting "enemies" into other file and changing variables directly in the file?

1
  • did you import enemies.py into grail.py? If so, add an argument to the functions, def frenchman(thing): ... then in the class pass self as the argument. In the functions, operate on thing - thing.number = 1 .... Commented Jan 20, 2016 at 21:11

2 Answers 2

2

Problem

You need to hand over the object as argument.

In the function:

def knightofni(obj):
    obj.number = 1
    obj.who = "We've encountered Knight of Ni."

and when using it in the class:

enemies.knightofni(self)

Do the same for frenchman().

Full code

grail.py

import enemies

class Encounter:
    def __init__(self):
        self.counter = 1
        self.number = 0
        self.who = "We've encountered no one."

    def forward(self):
        if self.counter == 1:
            enemies.knightofni(self)
        elif self.counter == 2:
            enemies.frenchman(self)
        else:
            self.number = 42
            self.who = "We've found the Grail!"
        self.counter += 1

knight = Encounter()
for i in range(4):
    print(str(knight.number) + " " + knight.who)
    knight.forward()

and enemies.py:

def knightofni(obj):
    obj.number = 1
    obj.who = "We've encountered Knight of Ni."

def frenchman(obj):
    obj.number = 4
    obj.who = "We've encountered French."

Output:

0 We've encountered no one.
1 We've encountered Knight of Ni.
4 We've encountered French.
42 We've found the Grail!
Sign up to request clarification or add additional context in comments.

Comments

0

It is possible to do this, though I don't know why you would really want to do it this way.

In your forward and __init__ methods you'll notice that you are passing in self, which is the instance of Encounter you are operating on. That is why you can do self.number = 42 and get the correct number when you call knight.number.

Since self is just an object you can pass it into the functions in 'enemies.py'.

Try:

# grail.py
def forward(self):
    if self.counter == 1:
        enemies.knightofni(self)
    elif self.counter == 2:
        enemies.frenchman(self)
    else:
        self.number = 42
        self.who = "We've found the Grail!"
    self.counter += 1

#enemies.py
def knightofni(that):
    that.number = 1
    that.who = "We've encountered Knight of Ni."

def frenchman(that):
    that.number = 4
    that.who = "We've encountered French."

2 Comments

I want it to be possible to add other "enemies" without making lengthy code in this place (so "forward()" is kind of a wrapper, place where it is decided what to do in different situations). It is also more readable if this functions are in different file. Think of situation where there would be 100 "enemies" and each would need to change 100 variables which are lists with 1M entries each. Is there a better way than putting "enemies" into other file and changing variables directly in the file?
@m_i-k_i Hmm, if that data is that unusually large I understand.

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.