使用函数创建 class 属性

Creating a class property using a function

我找到了这个奇幻名字生成器 here

我正在尝试调整代码以满足我的目的。我想使用 class NPC 中的函数 name_gen 自动创建一个 NPC 名称。 NPC特征为:

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

我需要的名称生成器代码如下:

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

现在我认为我唯一还需要做的就是从 class NPC 中生成名称。我想做类似的事情:

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")

但我不明白如何让 name_gen 函数检查 class NPC 属性, 以便它生成所需的名称。

有人可以帮我吗?

编辑

感谢您提供所有解决方案!我对 Python 很陌生;为了测试 Samwises 解决方案,我尝试使用下面的代码 运行 它作为一个单独的脚本(以检查我是否会得到一个名字)。但是它不打印任何东西。我将其放入编辑中,因为我认为这可能是一个微不足道的问题。如果值得发布一个单独的问题,请告诉我:

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)

我认为您对 OOP 概念感到困惑。

首先,让我们编辑您的 class:

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

看,我已经为属性分配了参数值。 现在让我们更改您的函数:

def name_gen(gender):
    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")
    return name

我在这里为您的函数添加了一个参数,因为您正在使用它的值。 现在让我们为您的 class.

创建一个实例
npc = NPC("Vishwas", 25, "M") # Instance of the class
print(name_gen(npc.gender)) # Print generated name

你的名字生成器有点 over-complicated IMO。我建议将所有文件读取和名称选择内容包装在一个简单的 class 中,这样您就可以定义一次,然后为每个名称列表实例化它。将文件读取部分放在 __init__ 中意味着每个列表只执行一次,而不是每次需要选择名称时 re-reading 文件。

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)

现在您可以定义三个 NameChooser 和一个从中选择的 name_gen 函数:

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()}"

现在您可以定义一个 NPC class,它将 agegender 作为构造函数的参数,并使用 [=19= 选择一个随机名称]:

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)"

实现自动发生的一种直接方法是使用 NPC.__init__() 方法简单地调用名称生成器。在下面的代码中,通过以下划线字符开头的名称使其成为 class 的私有方法。请注意,对它的调用必须等到它引用的所有实例属性都已分配值。

from random import randrange


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

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


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

if __name__ == '__main__':
    npc1 = NPC(25, 'M')
    print(f'{npc1.name!r}')
    npc2 = NPC(21, 'F')
    print(f'{npc2.name!r}')