这是计数器的类定义(文件名:计数器.py)在复杂的应用中
class Counter:
def __init__(self):
self.count = 0
def incr(self):
self.count += 1
def decr(self):
self.count -= 1
事实证明,这个类只会被实例化两次。这两个实例将由多个模块使用。你知道吗
创建Counter类的两个实例的正确方法是什么,以便两个实例的状态可以在整个应用程序中共享?
下面是我提出的解决方案
class Counter:
def __init__(self):
self.count = 0
def incr(self):
self.count += 1
def decr(self):
self.count -= 1
fileCounter = Counter()
httpCounter = Counter()
从另一个模块开始,我会做以下工作
from counter import fileCounter, httpCounter
def readMoxyConfig():
# Do read the file here
fileCounter.incr()
def callMoxyAPI():
# Make the HTTP rest call here
httpCounter.incr()
这种方法有漏洞吗?如果是的话,达到同样结果的正确方法是什么?
注意:我不想明确地知道全局变量是如何在this question中共享的。我想知道的是从同一个类实例化多个对象并从应用程序中的任何位置访问实例的正确方法。你知道吗
唯一的漏洞是你会是mutating global state,这通常是不赞成的原因有很多。您可以在
main
函数中实例化计数器,并将它们传递给需要它们的对象/方法以避免此问题。或者您可能认为全局可变状态适合您的用例,但这至少是您应该考虑的问题。你知道吗阅读链接文章,了解与全局可变状态相关的问题以及如何避免它。你知道吗
这个全局可变状态是怎样的?
像
fileCounter
、httpCounter
这样的模块级变量是全局变量,因为代码的任何部分都可以通过导入模块来访问它们(请注意,这与Python中的global
关键字不同)。它们在.count
中保持状态,可以通过调用incr()
或.decr()
或仅仅赋值来改变状态。你知道吗通过使实例成为函数的本地实例,代码的其他部分将无法再访问它们,除非显式地传递它们。你知道吗
正确的方法
你的解决方案是“正确的”,因为它会起作用。但它会导致一些你必须意识到的问题。这就是我的答案。你知道吗
实际上,“从应用程序的任何地方访问实例”这件事都是有问题的。随着对象变得越来越复杂,从应用程序的更多部分以更多的方式访问,它会使复杂性增加。你知道吗
我会做的有点不同。这样您就可以在需要时向两个不同的计数器类添加代码。在
counter.py
中:这样,如果您需要进入其中一个类,可以将其添加到
httpCounter
或fileCounter
。或者如果这两个类都有额外的代码,它可以进入Counter
类。你知道吗此外,如果愿意,还可以更改
increment
/decrement
/start
值。你知道吗我认为您可以使用Multiton模式(这里使用Multiton decorator)来避免全局可变州。在这个例子中,类“MyClass”本身的行为就像它的Multiton一样
Multiton
def multiton(cls): instances = {} def getinstance(name): if name not in instances: instances[name] = cls() return instances[name] return getinstance @multiton class MyClass: pass a = MyClass("MyClass0") b = MyClass("MyClass0") c = MyClass("MyClass1") print a is b # True print a is c # False
;相关问题 更多 >
编程相关推荐