2012-02-27 2 views
4

Я использую Python. Я читал немного об этом и, похоже, не могу обдумать его. То, что я хочу сделать, - это класс, называемый Зельями с различными предметами зелья. На данный момент есть одно зелье, простое HealthPotion. Я хочу, чтобы зелья были штабелированы в запасах и магазинах. Поэтому мне нужен экземпляр суммы зелья для инвентаря и экземпляра для каждого магазина, в котором есть зелья. Количество зелья было бы динамичным, для покупки/продажи и разграбления зелий. Если кто-то может дать основное объяснение или примеры, которые были бы замечательными.Python, создающий несколько экземпляров для одного объекта/класса

Вот отрывок из того, что у меня есть:

class Potion(Item): 
    def __init__(self, name, desc, val, amt, type, effect, bound): 
     Item.__init__(self, name, desc, val, amt, type, effect, bound) 

     self.name = name 
     self.desc = desc 
     self.val = val 
     self.amt = amt 
     self.type = 0 #Restorative 
     self.effect = effect 

    def use(self, you): 
    #Use health potion 
     you.hp_current += self.effect 
     you.displayStats() 

#Format: Name, Description, Value, Amount, Type, Effect, Bound 
HealthPotion = Potion('Health Potion', 'Restores 10 hit points when consumed', 10, 0, 
0, 10, 0) 

В идеале количество по умолчанию будет установлено в 0, и я был бы в состоянии объявить, сколько определенный магазин хотел бы начать с их наличием. Запасы и инвентарь устанавливаются в виде массива, который добавляется и удаляется в/из. Я думаю, что у меня есть логика для того, как это будет работать, у меня просто возникают проблемы с созданием сумм.

EDIT: Это часть того, что у меня есть в методе покупки, чтобы узнать, что произойдет без использования экземпляров. Это довольно уродливо, и я заметил, что you.inventory.y.amt не будет работать. y - выбранный элемент из списка элементов, отображаемых в «магазине».

  x = selection - 1 #Item menu starts at 1. But arrays start at 0. So it takes user input and subtracts 1 to match the array. 
      y = self.stock[x] 

      if y.val <= you.coin: 
       if y.amt == 0: 
        you.inventory.append(y) 
        you.inventory.y.amt += 1 
       else: 
        you.inventory.y.amt += 1; 

       you.coin -= y.val 
       self.funds += y.val 

       if self.stock.y.amt > 1: 
        self.stock.y.amt -= 1 
       else: 
        self.stock.y.amt -= 1 
        self.stock.pop(x) 

Я посмотрел на примерах, как это:

class foo: 
a = 1 
i = foo() 
foo.a => 1 
i.a => 1 
i.a = "inst" 
foo.a => 1 
i.a => "inst" 

мне интересно, если я не просто создать второй объект HealthPotion, но это не звучит для меня. Этот пример заставляет меня думать иначе. Может быть, я просто не понимаю, что происходит.

"Это позволило бы создать первый объект класса Employee"

emp1 = Employee("Zara", 2000) 

"Это позволило бы создать второй объект класса Employee"

emp2 = Employee("Manni", 5000) 

Спасибо!

+2

Итак, что конкретно представляет собой ваша проблема? Что вы пытались решить вашу проблему? – Marcin

+1

Не решение вашей проблемы, но вам не нужно будет устанавливать переменные-члены в инициализации зелья, если вы вызываете ваш суперкласс init. – Marcin

+0

Возможно, вы захотите использовать аргументы named keyword вместо комментария при конструировании. ('health_potion = Potion (name =" Health Potion ", desc =" Restores ... ", ...') – Daenyth

ответ

10

Я думаю, у вас может быть немного ошибочная концепция того, как работают классы и экземпляры. Это может иметь смысл, если вы подумаете о людях.

Предположим, мы хотим моделировать людей в нашей иерархии классов. На данный момент, человек должен иметь имя, и если вы спросите их говорить, они говорят, что их название:

class Person(object): 
    def __init__(self, name): 
     self.name = name 

    def speak(self): 
     print "Hi! My name is {self.name}.".format(self=self) 

Затем экземпляр Person, ну, человек! Например:

>>> basil = Person("Basil") 
>>> polly = Person("Polly") 
>>> 
>>> basil.speak() 
Hi! My name is Basil. 
>>> polly.speak() 
Hi! My name is Polly. 
>>> basil == polly 
False 

Так экземпляр не вид человека - это на самом деле просто человек.

У вас нет класса, чьи экземпляры сами являются занятиями, я слышал, вы спрашиваете? Да, конечно ты можешь! Он называется метаклассом и является очень мощным инструментом при определенных обстоятельствах. Однако, это не так.


Теперь, если вы посмотрите на ситуацию, видите ли вы разницу?A HealthPotion не является конкретным зельем (скажем, это в моем кармане) - это вид зелье. И способ, которым мы выражаем это отношение, - это наследование классов: определить новый класс HealthPotion, который наследует от Potion. Затем вы можете иметь экземпляры этих (в моем кармане, в магазине, где угодно). Если вы хотите использовать зелье, вы используете конкретный один экземпляр класса.

+0

Спасибо, спасибо, спасибо. Это делает больше смысла. Вы помогли распутать беспорядок, который был моим умом.:] Я действительно считаю, что мое понимание того, как делать то, что я хотел сделать, было немного. Благодаря! – TechnoCat

+0

@SarahMac без проблем, рад помочь =) дайте мне знать, если вы хотите, чтобы рука разработала новую структуру наследования. – katrielalex

2

Код, который у вас есть, использует очень запутывающие соглашения об именах, которые, как мне кажется, вызывают путаницу --- HealthPotion не является классом, это экземпляр, но имя CamelCase предполагает, что это класс в python.

Чтобы иметь несколько зелий здоровья, используя свой класс зелий, просто сделать

health_potion_1 = Potion("Health Potion", ...) 
health_potion_2 = Potion("Health Potion", ...) 
foobar_potion_1 = Potion("Foobar Potion", ...) 
#... 

Хотя это довольно плохой стиль, что вы, вероятно, хотите, чтобы иметь возможность легко создавать здоровья и подобные зелья, с тем же свойства и микстур с различными эффектами

для этого вы должны иметь

class HealthPotion(Potion): 
    def __init__(self, name="Health Potion", effect=10): 
     super(HealthPotion, self).__init__(name, "Restores %d points of health" % (effect,), effect, 0, 0) 
    def use(self, you): 
     you.hp_current+=self.effect 

Если вы хотите иметь несколько элементов в качестве Invento ry было бы проще просто иметь список (или набор или некоторую коллекцию) для вашего инвентаря и иметь несколько экземпляров в списке, например.

inventory = [HealthPotion(), HealthPotion()] 

Если вы хотите сделать укладку, я до сих пор считаю, что это функция инвентаризации, а не пункт (за пределы item.stackable члена), так что я бы иметь Inventory класс, который обрабатывает коллекции объекта, то, что содержание лица, сундука или магазина. простая реализация будет оберткой

inventory = [(HealthPotion(), 2)] 

где любые одинаковые элементы представлены в виде пары пункта и количество

В качестве альтернативы, это довольно легко превратить бывший в последний, если у вас есть a stacks_with метод:

def stack_size(item, inv): 
    "The number of items that will stack with item in inv" 
    return len([i for i in inv if item.stacks_with(i)]) 

def stacked_inventory(inv): 
    # if there is no stackable pair in the first i items 
    # (i.e. the stack size for that item is 0 in inv[0:i]), 
    # then the 'i'th item is a new stack, 
    # with stack_size(inv[i], inv) items in it 
    stacks = [ (inv[i], stack_size(inv[i])) 
        for i in range(0,len(inv)) 
        if not stack_size(inv[i], inv[0:i])] 
    return stacks 
+0

Это было очень полезно, спасибо вам большое. Первоначально я использовал свой HealthPotion как-то вроде weak_potion, но в итоге менял имя, чтобы проверить что-то с помощью метода использования и никогда не менял его. Я буду уделять больше внимания моим соглашениям об именах. Спасибо! – TechnoCat

+0

@SarahMac добавил, как я бы использовал инвентарь – tobyodavies

Смежные вопросы