Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a class to another class (Python)

Tags:

python

class

I'm having some trouble with classes at the minute, and I not sure of how to solve my problem. I've read the docs and I can't connect anything said there with the problem I'm having.

I'm trying to make some simple classes for a game. I have a Weapon class and a Person class. I'm trying to pass a Weapon to the Person class (I hope this makes sense), so that the Person (Bob) can use the weapon. I'm having trouble accessing the methods and attributes in the Weapon class. I've considered making Person a child class of Weapon so that it can call the method easily, but that doesn't seem intuitive to me . . .

class Weapon:
    def __init__(self, weapon_name, weapon_damage):
        self.weapon_name = weapon_name
        self.weapon_damage = weapon_damage

    def display_weapon_name(self):
        print('Weapon Name: %s' %self.weapon_name)


class Person:

    def __init__(self, person_name, health, ranged_weapon):
        self.person_name = person_name
        self.health = health
        Weapon.ranged_weapon = ranged_weapon

    def display_person_info(self):
        print('Name: %s' %self.person_name)
        print('Ranged Weapon :%s' %Weapon.display_weapon_name)

def ranged_attack(self, ranged_weapon, target):
    target.health -=ranged_weapon.weapon_damage
    print("Weapon: %s" %ranged_weapon.weapon_name)
    print(target.person_name + "'s Health: "+str(target.health))

pistol = Weapon("Pistol", 40)
bob = Person("Bob", 100, pistol)

bob.display_person_info()

Running this gives me:

Name: Bob
Ranged Weapon :<function Weapon.display_weapon_name at 0x02E23030>

Running:

bob.ranged_attack(pistol, bob)

Gives:

Weapon: Pistol
Bob's Health: 60

My questions are, am I passing the Weapon object correctly to the Person class? It seems weird writing Weapon.ranged_weapon in _init__ rather than self.ranged_weapon.

How can I get the display_weapon_info to show the string 'Weapon Name: Pistol', rather than the reference? It seems to work when I call it in ranged_attack, but not in the display info.

Really appreciate any help I can get with this. Apologies if a similar question has been asked before, but I couldn't find anything I could relate to my issue.

Rich

like image 755
Rytchbass Avatar asked May 02 '15 18:05

Rytchbass


People also ask

How do you pass a class to another class in Python?

If you want to extend another class in Python, taking all of its functionality and adding more functionality to it, you can put some parentheses after your class name and then write the name of the class that you're inheriting from.

Can you pass a class in Python?

yes of coarse you can pass classes or functions or even modules ...

Can we give class as argument to another class?

As Java Class , we can have classes as part of another class. i.e. we can have a user defined type inside another user defined type. e.g., room having fan and lights, car having engine and tyres. This way of including classes inside other classes is also referred as class composition or has a relation. .


2 Answers

Person doesn't actually need to reference the Weapon class directly; it just needs to save a reference to whatever is passed as the ranged_weapon argument and know what it can do with that object. The code implicitly assumes that ranged_weapon is an instance of Weapon, but will work with any object that is suitably similar to an instant of Weapon.

class Person:

    def __init__(self, person_name, health, ranged_weapon):
        self.person_name = person_name
        self.health = health
        self.weapon = ranged_weapon

    def display_person_info(self):
        print('Name: %s' %self.person_name)
        # display_weapon_name already calls print; but
        # you probably don't need this method at all.
        self.weapon.display_weapon_name()
        # Instead, do this (actually, you already do this
        # in ranged_attack())
        # print('Weapon: %s' % self.weapon.weapon_name)


    def ranged_attack(self, ranged_weapon, target):
        target.health -= self.weapon.weapon_damage
        print("Weapon: %s" % self.weapon.weapon_name)
        print(target.person_name + "'s Health: "+str(target.health))
like image 86
chepner Avatar answered Sep 30 '22 19:09

chepner


def display_person_info(self):
        print('Name: %s' %self.person_name)
        print('Ranged Weapon :%s' %Weapon.display_weapon_name)

Looking at this function, the compiler sees the following:

Line 1: A function named display_person_info with the parameter self.
Line 2: Print "Name: " and then print the name of self
Line 3: Print "Ranged Weapon: " and then Weapon.display_weapon_name.

In line 3, the compiler, rather than printing the weapon name, it is printing the function display_weapon_name itself! What you need to do instead is replace Line 3 with this:

print('Ranged Weapon :%s' %self.weapon.display_weapon_name())

That way, the value returned by the function is printed, rather than the function's pointer.

like image 44
hyper-neutrino Avatar answered Sep 30 '22 20:09

hyper-neutrino