简体   繁体   English

如何使用字典式创建对象?

[英]How to use dictonary to create an object?

I'm new in stackoverflow and I'd like to make my first question for a problem in this code I've tried to write to learn objects in python. 我是stackoverflow的新手,我想针对我试图编写以学习python对象的这段代码中的问题提出我的第一个问题。 I'm trying to call the creation of an object through a dictionary. 我试图通过字典调用对象的创建。 My purpose is to create an object thanks to a number, for example I have the dictionary newch = {1 : Character.new_dragon(), 2 : Character.new_goblin()} and when I call Player1 = newch[1] it should create a new dragon (@classmethod new_dragon) and assign it to Player1 我的目的是通过数字创建对象,例如,我有字典newch = {1 : Character.new_dragon(), 2 : Character.new_goblin()} ,当我调用Player1 = newch[1]它应该创建新龙(@classmethod new_dragon)并将其分配给Player1

The problem is that when i run the program, Character.new_dragon() and Character.new_goblin() are called automatically (i put a control print), but when I write "DRAGO" after the request "which player?" 问题是,当我运行程序时, Character.new_dragon()Character.new_goblin()被自动调用(我放置了控制打印),但是当我在请求“哪个播放器?”之后写入“ DRAGO”时 the functions aren't called because there isn't the control print 因为没有控件打印,所以未调用函数

import random

class Character:
    def __init__(self,idd,height,weight,att,defe):
        self.idd=idd
        self.height=height
        self.weight=weight
        self.att=att
        self.defe=defe


    @classmethod
    def new_goblin(cls):
        print('newgoblin')
        return cls(1,getr(1,1.5,0.1),getr(40,60,0.5),getr(5,15,1),getr(6,10,1))

    @classmethod
    def new_dragon(cls):
        print('newdrago')
        return cls(2,getr(20,30,1),getr(500,2000,5),getr(50,150,3),getr(20,100,3))


def getr(start,stop,step):          #returns float
    x=random.randint(1, 1000)
    random.seed(x)
    return random.randint(0, int((stop - start) / step)) * step + start


play={1:'p1', 2:'p2', 3:'p3', 4:'p4'} #dict for players
newch={1:Character.new_dragon(),2:Character.new_goblin()} ############This doesn't work


i=1       
while True:
    char=input("which player? Drago or Goblin?").upper()
    if(char=="DRAGO"):
        play[i]=newch[1]  #here i try to call Character.new_dragon()
        i+=1
        break
    elif(char=="GOBLIN"):
        play[i]=newch[2]
        i+=1
        break
    print("write \'Drago\' or \'Goblin\'")

print(play[1].height, play[1].weight, play[1].att, play[1].defe)

Here's my code, if you could help me, I would be very glad, thanks 这是我的代码,如果您能帮助我,我将非常高兴,谢谢

The new object is created immediately when you call Character.new_dragon() , and the object is then stored in the dict. 当您调用Character.new_dragon() ,将立即创建新对象,然后将该对象存储在dict中。

Instead you could not store the object in the dict, but the function that creates it. 取而代之的是,您无法将对象存储在dict中,但是可以创建它的函数。 That function would be Character.new_dragon (without the () ). 该函数将是Character.new_dragon (不带() )。 Then you can call that function when the player selects a character: play[i]=newch[1]() 然后,当玩家选择一个角色时,您可以调用该函数: play[i]=newch[1]()

Complete code: 完整的代码:

import random

class Character:
    def __init__(self,idd,height,weight,att,defe):
        self.idd=idd
        self.height=height
        self.weight=weight
        self.att=att
        self.defe=defe


    @classmethod
    def new_goblin(cls):
        print('newgoblin')
        return cls(1,getr(1,1.5,0.1),getr(40,60,0.5),getr(5,15,1),getr(6,10,1))

    @classmethod
    def new_dragon(cls):
        print('newdrago')
        return cls(2,getr(20,30,1),getr(500,2000,5),getr(50,150,3),getr(20,100,3))


def getr(start,stop,step):          #returns float
    x=random.randint(1, 1000)
    random.seed(x)
    return random.randint(0, int((stop - start) / step)) * step + start


play={1:'p1', 2:'p2', 3:'p3', 4:'p4'} #dict for players
newch={1:Character.new_dragon,2:Character.new_goblin} ############This doesn't work


i=1       
while True:
    char=input("which player? Drago or Goblin?").upper()
    if(char=="DRAGO"):
        play[i]=newch[1]()  #here i try to call Character.new_dragon()
        i+=1
        break
    elif(char=="GOBLIN"):
        play[i]=newch[2]()
        i+=1
        break
    print("write \'Drago\' or \'Goblin\'")

print(play[1].height, play[1].weight, play[1].att, play[1].defe)

This works, however I would not say it is the best coding style. 这行得通,但是我不会说这是最好的编码风格。 Its hard to judge from only this piece of code, but it might be a better idea to make Drago and Goblin subclasses of the Character class and store the type of those classes in that dictionary. 仅通过这段代码很难判断,但是将Drago和Goblin成为Character类的子类并将这些类的type存储在字典中可能是一个更好的主意。

When you are initialising the dictionary this way: 当您以这种方式初始化字典时:

newch={1:Character.new_dragon(),2:Character.new_goblin()}

You are binding keys (1 and 2) to the return values of the new_dragon and new_goblin functions. 您正在将 (1和2)绑定到new_dragon和new_goblin函数的返回值 You need to bind the functions(without calling them) like so: 您需要像这样绑定功能(不调用它们):

newch={1:Character.new_dragon,2:Character.new_goblin} Notice there are no brackets! newch={1:Character.new_dragon,2:Character.new_goblin}请注意,没有括号!

And then, when you create players, you execute those functions like so: 然后,在创建播放器时,您将执行以下功能:

play[i]=newch[1]() Notice here we have brackets! play[i]=newch[1]()注意这里有括号!

Additionally, if I may suggest an improvement of the code here: 此外,如果我建议在这里对代码进行改进:

if(char=="DRAGO"):
    play[i]=newch[1]()
    i+=1

To avoid the if statement, you can create you mapping with a string: 为了避免if语句,可以使用字符串创建映射:

newch={"DRAGO":Character.new_dragon,"GOBLIN":Character.new_goblin}

And create instances just by calling 并只需调用即可创建实例

play[i]=newch[char]()

To handle errors, you can add just a single if statement checking whether the char string is in the list with dict keys. 要处理错误,您可以仅添加一个if语句,使用dict键检查char字符串是否在列表中。

newch={1:Character.new_dragon(),2:Character.new_goblin()}

As this is written, the new_dragon and new_goblin functions are called when the dictionary is created. 在编写本文时,在创建字典时将调用new_dragonnew_goblin函数。 This is why you are seeing them both run "automatically" every time you run your program. 这就是为什么您每次运行程序都看到它们都“自动”运行的原因。

If you instead declared the dict like: 如果改为将dict声明为:

newch={1:Character.new_dragon ,2:Character.new_goblin}

And later have something like: 然后有类似的东西:

if(char=="DRAGO"):
    play[i]=newch[1]()

(note the parenthesis after the newch[1] ) you should get what you want. (请注意newch[1]之后的括号),您应该得到想要的。

Incidentally, those break statements aren't necessary. 顺便说一句,这些break语句不是必需的。 The If/elif/else chain doesn't fall through like a switch statement in other languages. If / elif / else链与其他语言中的switch语句不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM