如何在Python中创建全局类(如果可能)?

时间:2010-10-22 19:12:08

标签: python class

假设我有一些正在处理的RPG函数......

def name_of_function():
     action

并希望在每个函数中实现ax类(见下文),而不必重写每个类。我如何将该类创建为全局类。我不确定我是否使用了正确的术语,但请帮忙。这一直让我难以创建基于文本的RPG游戏。全局类的一个例子很棒!

class axe:
    attack = 5
    weight = 6
    description = "A lightweight battle axe."
    level_required = 1
    price = 10

4 个答案:

答案 0 :(得分:7)

你无法在Python中创建任何真正全局的东西 - 也就是说,无论如何,任何模块都可以神奇地使用它。但是一旦你理解了模块和导入工作的方式,这几乎不重要。

通常,您可以创建类并将它们组织到模块中。然后将它们导入到需要它们的任何模块中,这会将类添加到模块的符号表中。

因此,例如,您可以创建一个名为weapons.py的模块,并在其中创建一个WeaponBase类,然后从{{1}派生AxeBroadsword个类}}。然后,在需要使用武器的任何模块中,你都要放

WeaponsBase

位于文件顶部。执行此操作后,import weapons 会返回weapons.Axe类,Axe会返回weapons.Broadsword类,依此类推。你也可以使用:

Broadsword

from weapons import Axe, Broadsword Axe添加到模块的符号表中,允许代码完全按照您的要求执行操作。

您也可以使用

Broadsword

但由于两个原因,这通常不是一个好主意。首先,它会导入模块中的所有内容,无论您是否要使用它 - 例如from weapons import * 。其次,如果WeaponsBase中的某个函数与导入模块中的函数同名,则会遇到各种令人困惑的问题。

weapons系统中存在许多细微之处。例如,您必须小心确保模块不会尝试相互导入。最终,您的项目变得足够大,以至于您不希望将所有模块放在同一目录中,并且您必须了解import之类的内容。但你可以担心这一点。

答案 1 :(得分:2)

我不同意见,你不能在python中创建真正全局的东西。事实上,这很容易。在Python 3.1中,它看起来像这样:

def get_builtins():
  """Due to the way Python works, ``__builtins__`` can strangely be either a module or a dictionary,
  depending on whether the file is executed directly or as an import. I couldn’t care less about this
  detail, so here is a method that simply returns the namespace as a dictionary."""
  return getattr( __builtins__, '__dict__', __builtins__ )

就像其他一些东西一样,内置函数是Py3在细节上与Py2中的工作方式不同的一点。有关详细信息,请阅读python.org上的“Python X.X中的新功能”文档。我不知道上述公约的原因是什么;我只是想忽略那些东西。我认为上面的代码也应该在Py2中工作。

所以关键是这里有一个__builtins__东西,其中包含许多内容,因为内置于Python中。您已经爱上的所有summaxrange内容。好吧,差不多一切。但你真的不需要细节。你能做的最简单的事就是说

G          = get_builtins()
G[ 'G' ]   = G
G[ 'axe' ] = axe

代码中始终保证执行的位置。 G代表全局可用的命名空间,因为我在G内注册了GG现在神奇地超越了它存在于每个模块的背景中。意味着你应该小心使用它。如果命名冲突发生在G和模块命名空间中的任何内容之间,则模块的命名空间应该获胜(因为它首先被检查)。此外,当你告诉他们你正在污染全球的NAMESPACE犯罪时,请准备好让每个人都跳过你。我很惊讶,至今还没有人对此进行过共处。

嗯,那些人在某种程度上是对的。但是,就我个人而言,这是我的主要应用程序组合技术之一:您所做的就是从一个通用模块(不应该做这样的事情)向一个微调的应用程序特定命名空间迈出一步。你的模块不会在该命名空间之外工作,但是他们也不应该这样做。我实际上开始这种编程风格作为对(1)已建立的观点的实验性反叛,哈哈!和(2)每当我想用Python的import语句完成一些不那么微不足道的事情时,绝望就会降临。这些天,我只使用import作为标准库和定期安装的模块;对于我自己的东西,我使用自己开发的系统。我能说什么,它有效!

啊是的,还有两点:如果你喜欢这个解决方案,请自己帮个忙,给自己写一个监督你的publish()方法之类的方法永远不会发布已经被采用过的名字。在大多数情况下,你不希望这样。

最后,让我第二个第一个评论者:我一直按照你在上面展示的风格进行编程,因为你在教科书的例子中找到了(大部分时间使用car s,而不是{{1}确定)。出于相当多的原因,我几乎已经放弃了。

考虑这一点:JSON定义了七种数据:null,true,false,数字,文本,列表,字典,就是这样。我声称你可以使用那些建模任何其他有用的数据类型。

对于诸如套装,行李,有序词典等等,还有很多理由。这里的主张并不是说回归纯粹的JSON兼容表格总是方便或恰当的;声称只是可以模拟。现在,我正在实现一个稀疏列表用于消息传递系统, 数据类型i 在经典OOP中实现。这就是它的好处。

但我永远不会定义超出这些通用数据类型的类。相反,我编写的库采用通用数据类型并提供您需要的功能。我的所有业务数据(在您的情况下可能代表玩家,场景,工具等)都会进入通用数据容器(通常是axe s)。我知道这种架构方式存在开放性问题,但编程变得越来越容易,因为我通过BS打破了OOP宣传的一部分(除了真正有用和美好的东西,另一部分) OOP是)。

哦,是的,我提到过,只要您将业务数据保存在JSON兼容对象中,您就可以随时将它们写入磁盘并从磁盘中复活它们吗?或通过电线发送它们,以便您可以与远程玩家互动?如果你想这样做,那么序列化业务在古典OOP中会变得多么令人难以置信的扭曲(阅读this了解冰山一角)?在这个领域你必须知道的大多数技术细节对你的余生都毫无意义。

答案 2 :(得分:2)

您可以通过执行以下任一操作来添加(或更改现有的)Python内置函数和类,至少在Py 2.x中。之后,默认情况下,您添加的任何内容都可用于所有代码,但不是永久性的。

免责声明:由于可能存在名称冲突而导致此类事情可能会造成危险,并且因为它非常非显式而存在问题。但是,嘿,正如他们所说,我们都是成年人,对吗?

class MyCLass: pass

# one way
setattr(__builtins__, 'MyCLass', MyCLass)

# another way
import __builtin__
__builtin__.MyCLass = MyCLass

答案 3 :(得分:1)

另一种方法是创建一个单身人士:

class Singleton(type):
    def __init__(cls, name, bases, dict):
        super(Singleton, cls).__init__(name, bases, dict)
        cls.instance = None

class GlobalClass(object):
    __metaclass__ = Singleton
    def __init__():
        pinrt("I am global and whenever attributes are added in one instance, any other instance will be affected as well.")