olegje31
olegje31

Reputation: 43

Python: How to call a method from another module?

I have 2 files written in python. main.py looks like this:

import cats

class Dog():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("My name is "+self.name)

dog = Dog("Boxer")
cats.cat.talk()

and cats.py that looks like this:

class Cat():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("my name is "+self.name)
    def MakeDogTalk(self):
        dog.talk()
cat = Cat("pus")
cat.MakeDogTalk()

as you can see, i am trying to make the dog talk from the cats module, is there some way to make this work? My real world app looks nothing like this btw... of course,now i get this error:

line 9, in MakeDogTalk 
dog.talk()
NameError: name 'dog' is not defined

Upvotes: 3

Views: 15928

Answers (2)

Kevin
Kevin

Reputation: 76194

Generally, you should try to minimize the amount of file-level code in a module. In other words, if you intend to import a file, the executable code in that file should be inside a function or class when possible. cat = Cat("pus") and cat.MakeDogTalk() aren't inside a function or class, so I'd move them to main.py.

dog isn't going to be visible inside MakeDogTalk, so I would pass dog as a parameter to either the Cat constructor, or the MakeDogTalk method.

Approach 1: passing the parameter into the constructor

import cats
#main.py
class Dog():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("My name is "+self.name)

dog = Dog("Boxer")
cat = cats.Cat("pus", dog)
cat.MakeDogTalk()
cat.talk()

#cats.py
class Cat():
    def __init__(self, name, dog):
        self.name = name
        self.dog = dog
    def talk(self):
        print("my name is "+self.name)
    def MakeDogTalk(self):
        self.dog.talk()

Approach 2: passing the parameter into the method

import cats

class Dog():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("My name is "+self.name)

dog = Dog("Boxer")
cat = cats.Cat("pus")
cat.MakeDogTalk(dog)
cat.talk()

#cats.py
class Cat():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("my name is "+self.name)
    def MakeDogTalk(self, dog):
        dog.talk()

It would also be simple to keep all of your dog-based logic exclusive to main.py:

#main.py
import cats

class Dog():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("My name is "+self.name)

dog = Dog("Boxer")
cat = cats.Cat("pus")
dog.talk()
cat.talk()

#cats.py
class Cat():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("my name is "+self.name)

... But I assume you have a good reason in your real code to have the Cat handle it.


If it's really absolutely necessary to keep cat = Cat("pus") inside cats.py, then you'll have to put it inside a function. If it stays at the file-level scope, then MakeDogTalk will execute before import cats finishes executing, which occurs before the Dog class even exists, so that's a no-go. This adds a small complication that cats.cat will no longer be accessible from main.py, but you can still retrieve the object by returning it from the function call.

#main.py
import cats

class Dog():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("My name is "+self.name)

dog = Dog("Boxer")
cat = cats.do_cat_thing(dog)
cat.talk()

#cats.py
class Cat():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("my name is "+self.name)
    def MakeDogTalk(self, dog):
        dog.talk()

def do_cat_thing(dog):
    cat = Cat("pus")
    cat.MakeDogTalk(dog)
    return cat

It may also make sense to put the Dog class in its own file, too. Since the Cat class depends on the Dog class, the cats file should import the dogs file. This way, you can keep your cat = Cat("pus") in cats.py and at the file-level scope, if that's necessary for some reason.

#main.py
import cats

cats.cat.talk()

#cats.py
import dogs

class Cat():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("my name is "+self.name)
    def MakeDogTalk(self):
        dogs.dog.talk()

cat = Cat("pus")
cat.MakeDogTalk()


#dogs.py
class Dog():
    def __init__(self, name):
        self.name = name
    def talk(self):
        print("My name is "+self.name)

dog = Dog("Boxer")

Upvotes: 6

Kai
Kai

Reputation: 428

You are referencing dog in MakeDogTalk, but it doesnt know what it is. Add this to your MakeDogTalk:

    def MakeDogTalk(self):
        from main import dog
        dog.talk()

Upvotes: 1

Related Questions