Python 模块可以有属性吗?
是否可以向模块添加属性和特殊方法?我想定义一个模块,这样导入它就像类实例一样,而主体就像类定义一样。本质上,这是为了避免像这样难看的语法:Python 模块可以有属性吗?,python,properties,module,Python,Properties,Module,是否可以向模块添加属性和特殊方法?我想定义一个模块,这样导入它就像类实例一样,而主体就像类定义一样。本质上,这是为了避免像这样难看的语法: import game if game.Game().paused: print("The game is paused") _Speed = 1 @property def paused(): return _Speed == 0 例如,游戏模块如下所示: import game if game.Game().paused:
import game
if game.Game().paused:
print("The game is paused")
_Speed = 1
@property
def paused():
return _Speed == 0
例如,游戏模块如下所示:
import game
if game.Game().paused:
print("The game is paused")
_Speed = 1
@property
def paused():
return _Speed == 0
以及使用它的文件:
import game
if game.paused:
print("The game is paused")
此外,是否可以定义特殊方法(例如\uuu调用\uuu
)
要明确的是,我不区分类/实例方法,因为我使用的是game.game
作为单例/类
我已经使用@property和defining\uuuubool\uuuuu
进行了测试,但两者都没有达到我的预期效果
编辑(有关为什么要使用属性的信息):
我有一个属性
game.speed
,一个函数game.paused()
和一个函数game.pause(bool)
。基本上,我有一个临时变量,用于在游戏暂停时存储游戏速度。游戏暂停时,有一个私人速度变量设置为零。我不希望用户看到速度为零,并且能够在游戏暂停时修改速度,以便在游戏恢复时使用新的速度。我认为这是行不通的。您需要多次导入模块,Python将多次执行其内容。这将再次重置速度变量。我认为最好使用存储游戏状态的单个游戏类。它还将使您的代码更加清晰,易于理解。您似乎希望避免通过模块访问项目。这很容易做到
这两个是等效的:
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
如果您要查找的只是您提到的语法,那么您可以定义一个类并使用类级属性
a1.py
class Game(object):
paused = True
>>> from a1 import Game
>>> Game.paused
True
>>> Game.paused = False
>>> Game.paused
False
好的,正如您所问的,那么您可以使用属性装饰器和类方法做一些事情。像这样吗
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
Python并不关心
sys.modules
中的内容实际上是一个模块。所以你可以:
# game.py
class Game(object):
pass
import sys
sys.modules["game"] = Game()
现在,导入游戏的其他模块将获得游戏
实例,而不是原始模块
我不确定我是否推荐它,但它可以满足您的需要。这里的回答很好:
使用代理模式实现模块范围的属性。优雅
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项目)。为什么不直接使用来自game import game的?这些属性如何工作?元类?元类将如何引用游戏类?我是说如果您使用来自的。。。导入
语法,您不需要模块上的属性。使用您的模块的人不会期望模块上有属性,因此如果您从模块中删除属性并简单地使用表单。。。导入
在您自己的代码中,您可以获得相同的可读性,但您的API将更好地符合其他程序员的期望,这是一件好事。我更新了我的帖子,提供了更多信息。我有已计算的值,但应作为属性(与函数相反)。相关:--如果我将方法直接添加到模块对象,这是否可行?问题在于使用属性。我想计算暂停的,因为它从未被存储。@Darthfett-明白了。更新了我的答案。根据你链接的答案,它不适用于二传者。我试图给出一个实例,这就是为什么我没有提到这一点,但我也需要为游戏的其他成员提供setter。有没有理由你不能用实例属性定义类,不能在模块中将其实例定义为全局变量,不能从。。。导入
那样吗?是的,以这种方式设置程序可能不可行。使用Class变量设置状态如何?当然,它不是对称的,我想说你的实例化方法会更干净。我希望这个模块执行一次,我遇到的问题是为暂停的
创建一个属性接口。这就是你的方法不起作用的原因。你需要一个具有属性的类来存储或计算状态我不反对拥有一个类,如果我不必将它用作singleton/borg,每次我想使用一个值时都要创建一个实例。这种语法很难看。它要求我编写一个类来使用singleton/borg模式,方法将成员引用为self.*
或Game.*
,并且(对于borg模式)使用初始化器hack(以避免每次调用\uuu init\uuuu
都重新设置成员)。作为对第二个调用的响应,这是我最初尝试做的事情,但当我让游戏需要一个模块,然后那个模块需要游戏中的类实例时,问题就出现了。它会给你一个类似这样的错误:importorror:无法导入名称游戏
@Darthfett循环依赖项?还是我误解了你?游戏导入X和X导入游戏?在Python中,我们是“同意的成年人”<代码>游戏
不是您界面的一部分;game
实例是,因此在Pythonic视图中,不需要实例化控制“模式”。@Josh Smeaton是的,我不记得那个名字了。在我实际使用游戏中的东西时,所有东西都应该已经完全定义好了,所以如果我想导入一个全局文件,这只是个问题。哇。这是某种黑魔法,有一定的道理。毕竟,模块本身就是类的实例(types.ModuleType
)。实际上,您可以将游戏
类作为模块类型的子类编写,并实例化它,然后您就拥有了基本上是模块的东西。但正如我所说,Python实际上并没有检查类型。