2012-03-30 82 views
6

是否可以向模块添加属性和特殊方法?我想定义一个模块,以便导入它的行为类似于一个类实例,并且该实体充当类定义。基本上,这是为了避免丑陋的语法:模块可以有属性吗?

import game 
if game.Game().paused: 
    print("The game is paused") 

E.g.游戏模块是这样的:

_Speed = 1 

@property 
def paused(): 
    return _Speed == 0 

,并用它的文件:

import game 
if game.paused: 
    print("The game is paused") 

而且,是可以定义特殊的方法(如__call__)?

要清楚,我没有区分类/实例方法,因为我将game.Game用作单例/ borg类。

我已经使用@property进行了测试并定义了__bool__,但都没有按照我所希望的那样行事。

编辑(为什么我想用一个属性信息):

我有一个属性game.speed,功能game.paused()和功能game.pause(bool)。基本上,我有一个临时变量,用于在游戏暂停时存储游戏速度。当游戏暂停时,私人速度变量被设置为零。我不希望用户看到速度为零,并且能够在游戏暂停时修改速度,以便在游戏恢复时使用新速度。

+2

为什么不直接使用'from game import Game'? – 2012-03-30 05:09:37

+0

属性如何工作?元类?元类如何引用Game类? – Darthfett 2012-03-30 05:11:52

+2

我在说,如果你使用'from ... import'语法,你*不需要模块上的*属性。使用你的模块的人不会期望它有属性,所以如果你从模块中删除属性,并且只需在你自己的代码中使用'form ... import',你将获得相同的可读性,但是你的API会更好符合其他程序员的期望,这是一件好事。 – 2012-03-30 05:14:22

回答

11

的Python Soemthing不关心什么是在sys.modules实际上是一个模块。所以你可以:

# game.py 
class Game(object): 
    pass 

import sys 
sys.modules["game"] = Game() 

现在其他模块import game将得到Game实例,而不是原来的模块。

我不知道我推荐它,但它会做你想做的。

+4

哇。这是一些黑魔法。 – bukzor 2012-03-30 06:09:42

+0

太好了,谢谢! :) – Darthfett 2012-03-30 06:10:43

+1

它有一定的意义。毕竟,模块本身就是一个类的实例('types.ModuleType')。实际上,你可以将你的'Game'类写成模块类型的子类,实例化它,然后你就可以拥有基本上是模块的东西。但正如我所说,Python实际上并没有检查类型。 – kindall 2012-03-30 06:17:10

0

我不认为这是行得通的。您需要多次导入模块,Python将不止一次执行其内容。这将重新设置速度变量。我认为你最好使用存储游戏状态的单个Game类。它还会让您的代码更清晰易懂。

+0

我希望模块被执行一次,我遇到的问题是创建一个属性接口“已暂停”。 – Darthfett 2012-03-30 05:24:59

+0

这就是为什么你的方法不起作用。你需要一个具有属性的类来存储或计算状态 – 2012-03-30 05:37:26

+0

我不反对拥有一个类,如果我不必将它用作singleton/borg,并且每次我想要使用一个实例时都创建一个实例值。 – Darthfett 2012-03-30 05:52:39

2

看来你想避免通过模块访问项目。这很容易做到。

这两者是等价的:

import game 
if game.Game().paused: 
    print("The game is paused") 

from game import Game 
if Game().paused: 
    print("The game is paused") 

那好吧,这个怎么样:

# game.py 

class Game(object): 
    @property 
    def paused(): 
     return True 

game = Game() 

# from your module 
from game import game 
game.paused 
+0

这个语法很丑。它需要我编写一个类来使用单例/ borg模式,方法将引用成员的方法称为'self。*'或'Game。*',并且(对于borg模式)使用初始化方法hack(避免每次调用'__init__'时重新设置成员)。 – Darthfett 2012-03-30 05:28:10

+0

为了回应你的第二个问题,这是我一开始想要做的事情,但是当我有游戏需要一个模块时,结果是有问题的,然后该模块需要游戏中的类实例。它给你一个这样的错误:'ImportError:无法导入名称游戏' – Darthfett 2012-03-30 05:50:20

+0

@Darthfett循环依赖?或者我误解了你?游戏进口X和X进口游戏? – 2012-03-30 05:53:21

3

如果你正在寻找的是你提到的语法,那么你可以定义一个类和使用类级别的属性

a1.py

class Game(object): 
    paused = True 


>>> from a1 import Game 
>>> Game.paused 
True 
>>> Game.paused = False 
>>> Game.paused 
False 

那么,当你问到关于Properties on Class,那么你可以做一些与属性装饰器和classmethod。这样

class ClassProperty(property): 
    def __get__(self, cls, owner): 
     return self.fget.__get__(None, owner)() 

class Game(object): 
    stage = True 
    @ClassProperty 
    @classmethod 
    def paused(cls): 
     return Game.stage == True 

>>> from a1 import Game 
>>> Game.paused 
True 
+0

问题在于使用属性。我想'暂停'计算,因为它永远不会被存储。 – Darthfett 2012-03-30 05:23:40

+0

@Darthfett - 明白了。更新了我的答案。 – 2012-03-30 05:33:38

+1

根据你连接的答案,它不适用于setter。我试图给出一个[SSCCE](http://sscce.org/)这就是为什么我没有提到这一点,但我也需要其他成员的游戏引擎。 – Darthfett 2012-03-30 05:43:50

相关问题