[SOLVED] Creating a class property using a function

Table of Contents

Issue

I found this fantasy name generator here.

I am trying to adapt the code to suit my purpose. I want to create an NPC name automatically, using the function name_gen within the class NPC. With the NPC characteristics being:

class NPC:
  def __init__(self, name, age, gender):
    self.name = name_gen
    self.age = 25
    self.gender = M

The code from the name generator I need is the following:

from random import randrange

def line_appender(file_path, target):
    file = open(file_path, "r")
    splitfile = file.read().splitlines()
    for line in splitfile:
        target.append(line)

def name_selector(target_list):
    selected = target_list[randrange(len(target_list))]
    return selected

def name_builder(first_name_list_path, last_name_list_path):
    first_name_list = []
    last_name_list = []

    line_appender(first_name_list_path, first_name_list)
    line_appender(last_name_list_path, last_name_list)

    first_name_selected = name_selector(first_name_list)
    last_name_selected = name_selector(last_name_list)

    name = first_name_selected+" "+last_name_selected
    return name

Now the only thing I think I still need to do, is to generate the name from within the class NPC. I thought doing something like:

def name_gen
    if gender == "M":
    name = name_builder("first_name_male.txt", "last_name.txt")
    elif gender == "F":
    name = name_builder("first_name_female.txt", "last_name.txt")

But I don’t understand how to make the name_gen function check the class NPC properties,
so that it generates the desired name.

Could someone perhaps help me out?

EDIT

Thank you for all the solutions! I am pretty new to Python; In order to test Samwises solution, I tried to run it as a separate script (in order to check whether I would get a name) with the code below. It does however not print anything. I’m putting this in an EDIT because I think it might be a trivial question. If it is worth posting a separate question, please let me know:

import random

running = True

npc_input_messsage = "npc = NPC(25, 'M')"

class NameChooser:
    def __init__(self, file_path):
        with open(file_path) as f:
            self._names = f.read().splitlines()
    
    def choice(self):
        return random.choice(self._names)

first_choosers = {
    "M": NameChooser("first_name_male.txt"),
    "F": NameChooser("first_name_female.txt"),
}
last_chooser = NameChooser("last_name.txt")

def name_gen(gender):
    return f"{first_choosers[gender].choice()} {last_chooser.choice()}" 

class NPC:
    def __init__(self, age, gender):
        self.name = name_gen(gender)
        self.age = age
        self.gender = gender

while running:

    npc = input(npc_input_messsage)

# I'm entering npc = NPC(25, "M")

print(npc)

Solution

Your name generator is a little over-complicated IMO. I’d suggest wrapping all the file reading and name selection stuff in a simple class so you can define it once and then instantiate it for each of your name lists. Putting the file reading part in __init__ means you only do it once per list instead of re-reading the file each time you need to pick a name.

import random

class NameChooser:
    def __init__(self, file_path):
        with open(file_path) as f:
            self._names = f.read().splitlines()
    
    def choice(self):
        return random.choice(self._names)

Now you can define three NameChoosers and a name_gen function that picks among them:

first_choosers = {
    "M": NameChooser("first_name_male.txt"),
    "F": NameChooser("first_name_female.txt"),
}
last_chooser = NameChooser("last_name.txt")

def name_gen(gender):
    return f"{first_choosers[gender].choice()} {last_chooser.choice()}"

And now you can define an NPC class that takes age and gender as arguments to the constructor, and picks a random name using name_gen():

class NPC:
    def __init__(self, age, gender):
        self.name = name_gen(gender)
        self.age = age
        self.gender = gender

    def __str__(self):
        return f"{self.name} ({self.age}/{self.gender})"


npc = NPC(25, "M")
print(npc)  # prints "Bob Small (25/M)"

Answered By – Samwise

Answer Checked By – Candace Johnson (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.