模块可以有属性吗?

时间:2012-03-30 05:06:31

标签: python properties module

是否可以为模块添加属性和特殊方法?我想定义一个模块,以便导入它就像一个类实例,并且正文充当类定义。从本质上讲,要避免像这样的丑陋语法:

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)。从本质上讲,我有一个临时变量,用于在游戏暂停时存储游戏速度。有一个私人速度变量在游戏暂停时设置为零。我从不希望用户将速度视为零,并且能够在游戏暂停时修改速度,以便在游戏恢复时使用新的速度。

5 个答案:

答案 0 :(得分:12)

Python并不关心sys.modules中的内容实际上是一个模块。所以你可以:

# game.py
class Game(object):
    pass

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

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

我不确定我是否推荐它,但它会做你想要的。

答案 1 :(得分: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

答案 2 :(得分: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

答案 3 :(得分:0)

我不认为这会起作用。您需要多次导入模块,Python将多次执行其内容。这将再次重置速度变量。我认为你最好使用一个存储游戏状态的Game类。它还可以使您的代码更清晰,更容易理解。

答案 4 :(得分:0)

好的答案在这里:

http://jtushman.github.io/blog/2014/05/02/module-properties/

使用代理模式来实现模块范围的属性。优雅。

class Proxy(object):
    def __init__(self, local):
        self.local = local
    def __getattr__(self, name):
        return getattr(self.local(), name)

# aliasing for better syntax        
module_property = Proxy

class User(object):
    """Contrived User Object"""
    def __init__(self, **kwargs):
        self.name = kwargs.get('name', 'billy')
    def speak(self):
        print("Well hello there!")
    def say_hi(self, to_whom):
        print("Hi there {}".format(to_whom))

@module_property
def current_user():
  return User()

然后可以将其用作属性:

from login_manager import current_user, User

if __name__ == '__main__':
    print current_user.name
    current_user.speak()
    current_user.say_hi('lauren')

文章还提到了扩展此概念的可安装软件包(werkzerg项目)。