简体   繁体   English

如何从两个不同文件中的两个不同类中获取函数以相互通信?

[英]How do I get functions from two different classes in two different files to communicate with each other?

I'm trying to make a text-based RPG.我正在尝试制作基于文本的 RPG。 I have some code like:我有一些代码,例如:

heroes.py:英雄.py:

class Hero():
   def __init__(self):
      pass
   def Attack(self, target):
      # ...
   def TakeDamage(self, amount):
      # ...

monsters.py:怪物.py:

class Monster():
   def __init__(self):
      pass
   def Attack(self, target):
      # ...
   def TakeDamage(self, amount):
      # ...

The whole file structure looks like this:整个文件结构如下所示:

|__ backend
    __init__.py
    monsters.py
    heroes.py
MainGame.py

Let's say I want Monster and Hero to access each other's Attack and TakeDamage functions, for example:假设我想让MonsterHero访问彼此的AttackTakeDamage函数,例如:

class Monster():
   def __init__(self):
      pass
   def Attack(self, target):
      # ...
   def TakeDamage(self, amount, target:Hero):
      damage = # damage calculation here
      target.TakeDamage(damage)

How can I do this?我怎样才能做到这一点? So far I've tried:到目前为止,我已经尝试过:

  • Importing each other (eg from.monsters import Monster ) in their respective files - this gives me an error reading ImportError: cannot import name 'Monster' from partially initialized module 'backend.monsters' (most likely due to a circular import) .在各自的文件中相互导入(例如from.monsters import Monster ) - 这给了我一个读取ImportError: cannot import name 'Monster' from partially initialized module 'backend.monsters' (most likely due to a circular import)

Broadly speaking, classes don't have methods;广义上讲,类没有方法。 instances do.实例确实如此。 The purpose of a class is to define a data type. class 的目的是定义数据类型。 You don't need to see that definition, in Python, in order to use instances.您无需在 Python 中查看该定义即可使用实例。

Consider the code in the Monster class:考虑Monster class 中的代码:

   def TakeDamage(self, amount, target:Hero):
      damage = # damage calculation here
      Hero.TakeDamage(damage)

(I will ignore for the moment that the logic here probably doesn't make that much sense.) (我暂时忽略这里的逻辑可能没有那么大的意义。)

Writing :Hero is a hint - to the person reading the code, and possibly to third-party tools;写作:Hero是一个提示——给阅读代码的人,也可能给第三方工具; Python itself does not care - that target will be an instance of the Hero class. Python 本身并不关心- 该target将是Hero class 的一个实例。

We want to call a method on that instance, not on the class.我们想在该实例上调用一个方法,而不是在 class 上。 The class doesn't have a TakeDamage method; class没有TakeDamage方法; it only has a TakeDamage function , which is used to create the method when we look it up via an instance .它只有一个TakeDamage function当我们通过实例查找它时,它用于创建方法。

Therefore, the code should not say Hero.TakeDamage(damage) .因此,代码应该说Hero.TakeDamage(damage) It should say target.TakeDamage(damage) , because target is the name of the Hero instance whose method we will call.它应该是target.TakeDamage(damage) ,因为target是我们将调用其方法的Hero实例的名称。

To do this, we do not require the definition of the Hero class.为此,我们不需要Hero class 的定义。 monsters.py should not import anything to make this work. monsters.py不应该import任何东西来完成这项工作。

When the code is running, at the moment that the method call is attempted , Python will check whether the thing that is named target has a TakeDamage attribute.当代码运行时,在方法调用被尝试的那一刻,Python会检查名为target的东西是否有TakeDamage属性。 When it doesn't find one directly attached to the instance, it will look in the class, and find the TakeDamage function in that class.当它没有找到直接连接到实例的对象时,它将查看 class,并在该 class 中找到TakeDamage function。 It will automatically create a method from that.它将自动从中创建一个方法。 Then it will check that the TakeDamage that it got from this process is callable (spoiler: it is, because it's a method), and call it.然后它会检查它从这个过程中得到的TakeDamage是可调用的(剧透:它是,因为它是一个方法),然后调用它。

Here is a way for me to design this game:这是我设计这款游戏的一种方式:

├── backend
│   ├── __init__.py
│   ├── character.py
│   ├── heros.py
│   └── monsters.py
└── main.py

character.py is the common class between hero and monster. character.py是英雄和怪物之间常见的 class。

# character.py
class Character:
    def __init__(self):
        self.health = 100

    def attack(self, target):
        target.take_damage(1)

    def take_damage(self, amount):
        self.health -= amount

    def __repr__(self):
        return (
            f"{self.__class__.__name__}("
            f"health={self.health!r}"
            f")"
        )
# heros.py
from .character import Character

class Hero(Character):
    pass
# monsters.py
from .character import Character

class Monster(Character):
    def attack(self, target):
        target.take_damage(5)
# main.py
from backend.heros import Hero
from backend.monsters import Monster

h = Hero()
m = Monster()

h.attack(m)
m.attack(h)

print(h)
print(m)

Output: Output:

Hero(health=95)
Monster(health=99)

The key here is happening inside the attack method: it calls target.take_damage() with the amount.这里的关键发生在attack方法内部:它使用数量调用target.take_damage()

Note that heros.py does not import monsters.py and vice versa.注意heros.py不导入monsters.py ,反之亦然。 Doing so could result in circular reference, which is messy.这样做可能会导致循环引用,这很混乱。

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

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