所以我知道这可能被认为是一个非常广泛的问题,我很抱歉,但我在理解整个导入以及__init__
和self.
事情以及所有这些方面遇到了问题。 ..我已经尝试阅读Python文档和其他一些教程,但这是我的第一语言,我很少(很多)困惑。
到目前为止,在大学的第一个学期,我已经学习了Python,函数,数字类型,序列类型,基本逻辑内容的基础知识。但它的移动速度比我想要的慢,所以我自己尝试了解更多,并创建了一个基于文本,战略,资源管理的游戏,受到了Ogame的启发。
我遇到的第一个问题是如何定义每个建筑物,例如每个建筑物,它产生资源。我做了一些研究,发现课程很有用,所以每个建筑都有这样的东西:
class metal_mine:
level = 1
base_production = 15
cost_metal = 40
cost_crystal = 10
power_use = 10
def calc_production():
metal_mine.production = A formula goes here
def calc_cost_metal():
etc, same for crystal
def calc_power_use():
metal_mine.power_use = blah blah
def upgrade():
various things
solar_plant.calc_available_power()
有点长,我离开了很多。无论如何,有点重要的是最后一点,你看我升级矿井时,确定它是否有足够的动力来运行,我计算太阳能发电厂的功率输出({{1} }),其中包含许多类似金属矿类的东西。如果我把所有东西放在同一个模块中,这一切都很有效,但是对于许多建筑和研究水平等等,它会变得很长,我迷失了它。
所以我试着将它分成不同的模块,一个用于矿山,一个用于存储建筑,一个用于研究水平等。这使得一切都非常整洁,但是我仍然需要一种方法来调用类中的函数。现在是不同模块的一部分。我的初始解决方案是放置solar_plant.calc_output()
,这在大多数情况下使from power import *
类在solar_plant
类中可用。我在大多数情况下说,因为根据我尝试做事的顺序,有时似乎这不起作用。 metal_mine
类本身调用来自solar_plant
类的变量,现在我知道这已经变得非常spagetti-ish ..但我还不知道还有更好的约定。
无论如何,有时当我调用metal_mine
类时,它又会尝试调用solar_plant
类,它会说metal_mine
没有定义,这导致我以某种方式思考模块或类需要初始化?代码中的东西之间似乎有一些循环。根据我尝试和玩游戏的顺序,有时我会无意中这样做,有时候我不是。我还没有被教过导入和重装的惯例和细节以及所有这些......所以我不知道我是采取正确的方法还是其他任何方法。
如果我刚刚说的所有内容都有意义,我是否可以获得一些关于如何正确地使这些各种模块的内容免费提供并可修改给其他人的信息?我是不是想把事情分成不同的模块,你通常不会这样做,我应该只处理大模块?或者我输错了什么?还是...?
在旁注中,在大多数教程和地方,我都在寻求帮助,我看到了充满self.something和 init 函数的类或函数。我可以得到一个解释这个?或者是一个简单的第一次程序员教程的链接?
================== UPDATE =================
好吧太宽泛了,就像我想的那样。根据我得到的帮助,我想我可以缩小范围。
我整理了我认为需要成为类变量的内容,那些不会发生变化的内容 - metal_mine
,name
和base_cost_metal
,所有其他内容都取决于球员目前选择了那种类型的建筑物(假设他们可以有多个定居点)。
获取我现有的片段:
base_cost_crystal
所以根据我的理解,现在这是一个更正确定义的类?我使用它们的起始值定义实例变量,然后在用户播放时更改它们。
在我开始游戏的主要功能中,我会创建一个每个矿的实例,比如说class metal_mine:
name = 'Metal Mine'
base_cost_metal = 60
base_cost_crystal = 15
def __init__(self):
self.level = 0
self.production = 30
self.cost_metal = 60
self.cost_crystal = 15
self.power_use = 0
self.efficiency = 1
def calc_production(self):
self.production = int(30 + (self.efficiency * int(30 * self.level * 1.1 * self.level)))
def calc_cost_metal(self):
self.cost_metal = int(metal_mine.base_cost_metal * 1.5 ** self.level)
,然后我用
player_metal_mine = metal_mine()
因此,如果这是正确定义的,我现在只需为每个建筑物导入每个模块以及这些新模板吗?一旦它们被导入,并且创建了一个实例,所有新实例及其变量是否包含在主模块的范围(右侧术语?)中,这意味着不需要新的导入或重新加载?
如果答案是肯定的,我只需要导入,我应该使用什么方法?我理解只有>>> player_metal_mine.level
0
>>> player_metal_mine.upgrade()
>>> player_metal_mine.level
1
例如,但这意味着我必须使用import mines
来使用它,这比使用mines.player_metal_mine.upgrade()
之类的内容要多一点,或者更具体,from mines import *
,尽管最后一个选项意味着我需要从每个模块单独导入每个建筑物。就像我说的那样,提供,是的,我只是导入它,最好的方法是什么?
==================更新2 ================= (你可以跳过文字的墙,只读这个)
所以我经历了一切,纠正了我的所有课程,所有内容似乎都是使用from mines import metal_mine
正确导入的,但是我的变量范围代表了资源级别。
如果所有内容都在1个模块中,则在顶部我会声明每个变量并给它起始值,例如: from module import *
。然后,在我的类的任何改变它的方法中,例如升级建筑物,花费资源,或者在任何改变它的函数中,比如定期将所有生产添加到当前资源级别的那个,我放{{1}例如,在顶部。然后,在函数内,我可以调用并改变金属的值没问题。
但是现在我将这些类和函数从各个模块全部导入到1个模块中,函数无法找到这些变量。我认为会发生的事情是,在导入的过程中,我基本上会说,把这个模块中的所有东西都拿出来,并假装它现在在这个模块中,然后使用它。但显然这不是正在发生的事情。
在我的主模块中,我使用metal = 1000
导入我的所有模块,并将say global metal
的值定义为from mines import *
。现在我创建了一个金属矿的实例,`metal_mine_one = metal_mine(),我可以调用它的方法和变量,例如。
metal
但是,当我尝试调用类似1000
的方法,其中包含>>> metal_mine_one.production
30
,然后调用metal_mine_one.upgrade()
时,它会给出一个错误,指出未定义金属。就像我说的,如果这一切都在1个模块中,这个问题不会发生,但是如果我尝试导入东西,它就会发生。
那么如何以不会导致此问题的方式导入这些模块,并使我主模块的全局范围内的变量可用于所有导入模块中的所有函数和方法?
答案 0 :(得分:2)
这里要介绍的内容很多.. init 是一个内置方法,在创建类的实例时会自动调用。在您提供的代码中,您已经创建了一个类,现在您需要创建该类的实例。一个更简单的例子:
class Test:
def __init__(self):
print "this is called when you create an instance of this class"
def a_method(self):
return True
class_instance = Test()
>>> "this is called when you create an instance of this class"
class_instance.a_method()
>>> True
类方法中的第一个参数是* always本身。按照惯例,我们只称这个论点为“自我”。你的方法不接受任何参数,确保它们接受self(或者在它们之上有装饰器@staticmethod)。此外,请确保按self.a_method
或class_instance.a_method
答案 1 :(得分:2)
首先介绍面向对象编程。即班级。你应该想象一个类似蓝图的类,它展示了如何制作一些东西。当你创建一个类时,它描述了如何为程序创建一个对象。 python中的一个简单类可能看起来像这样。
class foo:
def __init__(self, bars_starting_value):
self.bar = bars_starting_value
def print_bar(self):
print(self.bar)
这告诉python如何制作一个foo对象。 init 函数称为构造函数。当你做一个新的foo时会调用它。 self是一种引用运行该函数的foo的方法。在这种情况下,每个foo都有自己的bar,可以使用self.bar在foo中访问它。请注意,您必须将self作为函数定义的第一个参数,这样才能使这些函数属于单个foo而不是所有函数。
有人可能会像这样使用这个类:
my_foo = foo(15)
my_other_foo = foo(100)
foo.print_bar()
foo.bar = 20
print(foo.bar)
my_other_foo.print_bar()
这将输出
15
20
100
就进口而言。它们采用在一个文件中定义的所有内容并将它们移动到另一个文件中定义。如果将类定义放在一个文件中,可以将其导入主程序文件并从那里创建对象,这很有用。
只要将变量提供给其他人,您就可以将所有生成器生成的功率传递给我的功能,以确定它是否具有足够的功率。
希望这有帮助。