如何给新对象赋予不同的属性,以及初始化是如何工作的?

2024-06-01 02:25:22 发布

您现在位置:Python中文网/ 问答频道 /正文

所有对象都有不同的随机名称变量,但所有对象都有相同的随机性别。 怎么会这样? 如何使所有对象具有不同的随机性变量? 我是否正确地使用了__init__,以及我必须向类方法添加什么?你知道吗

我正在做一个游戏,人口(物品清单)的人(从村民阶级的对象)。我想让他们得到随机的性别,然后类根据性别从名称列表中给每个对象随机命名。你知道吗

但是出了点问题,性从一开始就是不变的。但是,名字是不同的!你知道吗

你能帮我解决这个问题并提供更多相关文献吗?你知道吗

import random

mnames = ['Ivan', 'Oleg', 'Kirill']

fnames = ['Katya', 'Masha', 'Olga']

population = [1,1,1,1,1]

class villager:
    age = 0
    sex = random.randint(0,1)
    name = ''


    def __init__(self, sex = 10):
            self.sex = random.randint(0,1)


    def __init__(self, name = ''):
        if self.sex == 0:
            self.name =  mnames[random.randint(0, len(mnames)-1)]
        if self.sex == 1:
            self.name =  fnames[random.randint(0, len(fnames)-1)]

populsize = len(population)

for i in range(populsize):
    population[i] = villager()

for i in range(len(population)):
    print(population[i].sex, population[i].name )

我希望看到这样的情况:

1 Katya
0 Ivan
0 Ivan
0 Kirill
1 Olga

实际结果是(总是同性,第一个数字):

0 Kirill
0 Ivan
0 Oleg
0 Oleg
0 Oleg

或者

1 Olga
1 Katya
1 Masha
1 Olga
1 Katya

Tags: 对象nameselfleninitrandompopulationrandint
2条回答

首先,定义了一个类级属性

class villager:
    sex = random.randint(0,1)

这确保了villager的所有实例都有一个.sex属性,该属性在其定义处随机分配了一个默认值。你知道吗

然后定义一个__init__方法,该方法将sex指定为一个参数(该参数被忽略),但不管怎样都会分配一个随机数。你知道吗

    def __init__(self, sex = 10):

然后,它又被重新定义,从而覆盖了第一个定义:

    def __init__(self, name = ''):

第二个定义没有分配self.sex属性,因此这个类的每个新实例都将返回到类级属性(它被分配了一次)。结果就是你看到的,所有的村民都有相同的sex分配。你知道吗

在Python中,不能以这种方式构造同一方法的多个定义(可以通过使用特定的decorator来实现,但这里并不需要它)。最快的解决方法是将两个独立的__init__组合成一个定义,并实现您的意图:

class villager:

    def __init__(self, sex=None, name=None):
       if sex is None:
           self.sex = random.randint(0,1)
       else:
           self.sex = sex

       if name is not None:
           self.name = name
       else:
           if self.sex == 0:
               self.name = mnames[random.randint(0, len(mnames)-1)]
           elif self.sex == 1:
               self.name = fnames[random.randint(0, len(fnames)-1)]

所以对于这种情况,您的默认构造函数应该可以工作

>>> v = villager()
>>> v.sex
1
>>> v.name
'Olga'

现在还可以在构造函数中指定特定值:

>>> v1 = villager(name='Gangut')
>>> v1.name
'Gangut'
>>> v1.sex
1

或者直接用这两个参数

>>> v2 = villager(name='Elena', sex=1)
>>> v2.name
'Elena'
>>> v2.sex
1

Python不允许你像在C++中那样超载^ {< CD1>}。类中__init__的第二个定义覆盖了第一个定义。你知道吗

在您的代码中,sex的类级变量永远不会更改。不需要这些类级定义。你知道吗

class villager:
    #these aren't needed, better to set in __init__()
    #age = 0
    #sex = random.randint(0,1)
    #name = ''

    #this definition is overwritten by the next definition of __init__()
    def __init__(self, sex = 10):
            self.sex = random.randint(0,1)

定义类的正确方法是:

class villager:

    def __init__(self, sex=10, name=''):
        self.sex = random.randint(0,1)
        if self.sex == 0:
            self.name =  mnames[random.randint(0, len(mnames)-1)]
        if self.sex == 1:
            self.name =  fnames[random.randint(0, len(fnames)-1)]

因为代码不使用sexname,所以不需要在__init__方法中指定它们。如果您确实希望在实例化villager时设置它们,但也希望它们是可选的,您可以这样编写代码:

class villager:

    def __init__(self, sex=None, name=None):
        if sex is not None:   # must be specific because you define sex as 0,1
            self.sex = sex
        else:
            self.sex = random.randint(0,1)
        if name:
            self.name = name
        else:
            if self.sex == 0:
                self.name =  mnames[random.randint(0, len(mnames)-1)]
            if self.sex == 1:
                self.name =  fnames[random.randint(0, len(fnames)-1)]

相关问题 更多 >