4

在一个大型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?

4

2 回答 2

3

有时,您希望不同的客户端能够以不相互冲突的方式使用具有不同设置的模块。例如,Python 的random模块提供了一堆随机数生成函数,这些函数实际上是隐藏Random实例的绑定方法。大多数用户不太关心什么算法生成他们的随机数,或者其他模块是否会要求随机数会改变序列。但是,关心的用户可以获取自己的Random对象并生成随机数序列,而不会受到其他模块要求随机数的影响。

有时,现在全球性的东西可能并不总是全球性的。例如,如果你正在开发一个行星规模的 RTS,你可能有一个Planet只有一个实例的类,因为战斗只发生在一个行星上。然而,你不想排除建造类似行星湮灭的可能性,战斗跨越整个太阳系,并将灭绝事件的小行星作为超级武器投放。如果你去掉这个Planet类,让它的方法和属性成为模块级的,以后再回去添加更多的行星会困难得多。

有时,让对象而不是模块来做事更具可读性。例如,假设模块joebob定义了两个对象evil_overlord_bobgood_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_everythingstop_bob模块级别并完全摆脱 Bob 和 Joe 类和对象。但是,那么你会写

joebob.slaughter_everything()
joebob.stop_bob()

如果你能说清楚发生了什么

evil_overlord_bob.slaughter_everything()
good_guy_joe.stop_bob()

即使你永远不需要实例化 Bob 的同样邪恶的孪生兄弟greg_the_fleshripper

于 2013-07-19T19:14:28.573 回答
0

除了其他好处之外,使用类允许您对实例使用自省,这是您无法使用函数执行的操作。

以更一般的方式,这两种方法都是“pythonic”。使用其中一个真的取决于项目的类型(小/大,带/不带 GUI,...)

于 2013-07-19T19:12:23.507 回答