在一个大型 python 项目 (openerp) 中,我多次遇到以下模式:
在模块中,定义了一个类及其方法。然后,在同一模块中并在类定义之后立即实例化该类的实例,然后从其他模块调用该实例。
# in module_A.py:
class ClassA(object):
def __init__(self, default="Hello world!"):
self.default = default
def my_method(self, data):
print self.default
print data
object_a = ClassA()
对我来说,将方法定义为模块函数看起来更简单,没有类查找重载:
# in module_B.py:
default = "Hello world!"
def my_method(data):
print default
print data
从其他模块来看,用法很相似:
from module_a import object_a as prefix
prefix.my_method("I'm so objective!")
对比:
import module_b as prefix
prefix.my_method("I'm so modular!")
有什么理由更喜欢模式 A 而不是模式 B?还是模式 B 更符合 Python 风格?
最佳答案
有时,您希望不同的客户端能够以不同的设置使用您的模块,而不会相互冲突。例如,Python 的 random
模块提供了一堆随机数生成函数,它们实际上是隐藏的 Random
实例的绑定(bind)方法。大多数用户并不太在意什么算法生成他们的随机数,或者其他请求随机数的模块是否会改变序列。然而,关心的用户可以获得他们自己的 Random
对象并生成随机数序列,这些随机数序列不会受到其他请求随机数的模块的影响。
有时,现在是全局性的东西可能并不总是全局性的。例如,如果您正在开发行星规模的 RTS,您可能有一个包含一个实例的 Planet
类,因为战斗只发生在一个行星上。但是,您不想排除构建像行星毁灭之类的东西的可能性,战斗延伸到整个太阳系,并将灭绝事件小行星作为 super 武器转换。如果您摆脱 Planet
类并将其方法和属性设置为模块级别,那么稍后返回并添加更多行星将变得更加困难。
有时,让对象而不是模块来做事更具可读性。例如,假设模块 joebob
定义了两个对象 evil_overlord_bob
和 good_guy_joe
。
class Bob(object):
def slaughter_everything(self):
print "Muahahaha! Die for my amusement!"
class Joe(object):
def stop_bob(self):
print "I won't let you hurt those innocents!"
evil_overlord_bob = Bob()
good_guy_joe = Joe()
假设 Bob 和 Joe 是非常独特的人。很难想象您会想要创建另一个对象,例如 Bob 或 Joe。在这种情况下,您可以将 slaughter_everything
和 stop_bob
移动到模块级别,并完全摆脱 Bob 和 Joe 类和对象。然而,那么你会写
joebob.slaughter_everything()
joebob.stop_bob()
如果你能说的话就更清楚发生了什么
evil_overlord_bob.slaughter_everything()
good_guy_joe.stop_bob()
即使您永远不需要实例化 Bob 的同样邪恶的双胞胎兄弟 greg_the_fleshripper
。
关于python - 在其类定义之后立即实例化 python 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17753382/