在一个大型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更加pythonic?
答案 0 :(得分:3)
有时,您希望不同的客户端能够使用不同设置的模块,使它们不会相互冲突。例如,Python的random
模块提供了一组随机数生成函数,这些函数实际上是隐藏Random
实例的绑定方法。大多数用户并不太关心什么算法生成他们的随机数或者是否其他模块要求随机数会改变序列。但是,关注的用户可以获得自己的Random
对象并生成随机数序列,这些序列不会受到其他要求随机数的模块的影响。
有时候,全球性的东西现在可能并不总是全球性的。例如,如果您正在使用行星级RTS,那么您可能会有一个Planet
类,其中包含一个实例,因为战斗只发生在一个星球上。但是,你不想排除建立像行星湮灭这样的东西的可能性,在整个太阳系中进行战斗,并将灭绝事件小行星作为超级武器。如果你摆脱了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()
假设鲍勃和乔是非常独特的人。你想要创建像鲍勃或乔这样的另一个对象是不可想象的。在这种情况下,您可以将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
。
答案 1 :(得分:0)
除了其他好处之外,使用类允许您在实例上使用内省,这是函数无法做到的。
以更一般的方式,两种方法都是“pythonic”。使用其中一个真正取决于项目的类型(小/大,有/没有GUI,...)