xav*_*ras 1 python firefox singleton selenium-rc
我正在使用Python 2.7在os x 10.6上编写firefox 5.1和selenium webdrive v.2的测试套件.
除了创建单例类之外,一切都工作正常,这应该只保证一个firefox实例:
def singleton(cls):
instances = {}
def getinstance():
if cls not in instances:
instances[cls] = cls()
return instances[cls]
return getinstance
@singleton
class Fire(object):
def __init__(self):
self.driver = webdriver.Firefox()
def getdriver(self):
return self.driver
def close_(self):
self.driver.close()
def get(self, url):
self.driver.get(url)
return self.driver.page_source
f = Fire()
f.close_()
Run Code Online (Sandbox Code Playgroud)
此时如果我f=Fire() 再次打电话没有任何反应.不会创建新实例.我的问题是为什么我会看到这种行为?我怎么做的?
我的第二个问题,如果我输入:
isinstance(f, Fire)
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
Run Code Online (Sandbox Code Playgroud)
这对我来说很奇怪......根据我的理解它应该回归 True
最后一个问题:
当我有单身课时,我应该能够做到:
f = Fire()
f2 = Fire()
f2.get('http://www.google.com')
up to here works, but if I say
f.close_()//then
URLError: urlopen error [Errno 61] Connection refused
Run Code Online (Sandbox Code Playgroud)
我无法理解这一点.
就创建一个类的单个实例而言,你的装饰器对我来说似乎没问题,所以我没有看到你的问题#1.它没有做你想象的那样:每次你使用装饰器都有一个新的instances字典,而且里面只有一个项目,所以实际上没有任何理由在那里使用字典 - 你需要一个可变容器所以你可以修改它,但我会使用一个列表,或者在Python 3中,也许是一个nonlocal变量.但是,它确实执行其预期的功能,以确保只有一个装饰类的实例.
如果你问为什么在关闭它之后你不能创建一个新的对象实例,那么你没有编写任何代码来允许在那种情况下创建另一个实例,而且Python无法猜测你想要什么那会发生.单例意味着只有一个类的实例.你已经创建了那个实例; 你不能创造另一个.
对于#2,您的@singleton装饰器返回一个函数,该函数实例化(或返回先前创建的实例)该类.因此Fire,一个功能,而不是一个类,一旦装饰,这就是为什么你的isinstance()工作不起作用.
在我看来,对单身人士最直接的方法是将智慧放在一个类而不是装饰器中,然后从该类继承.从继承的角度来看,这甚至是有意义的,因为单例是一种对象.
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = object.__new__(cls, *args, **kwargs)
return cls._instance
class Fire(Singleton):
pass
f1 = Fire()
f2 = Fire()
f1 is f2 # True
isinstance(f1, Fire) # True
Run Code Online (Sandbox Code Playgroud)
如果你仍然想用装饰器做,最简单的方法是在装饰器中创建一个中间类并返回:
def singleton(D):
class C(D):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = D.__new__(cls, *args, **kwargs)
return cls._instance
C.__name__ = D.__name__
return C
@singleton
class Fire(object):
pass
Run Code Online (Sandbox Code Playgroud)
您可以将所需的行为注入到现有的类对象中,但在我看来,这是不必要的复杂,因为它需要(在Python 2.x中)创建方法包装器,并且您还必须处理被装饰的类已经有了__new__()自己的方法.
您可能认为可以编写一个__del__()方法,以便在没有对现有实例的引用时创建新的单例.这不起作用,因为总是存在对实例的类内部引用(例如,Fire._instance),因此__del__()永远不会被调用.一旦你有一个单身人士,它就会留下来.如果你在关闭旧单身后想要一个新的单身人士,你可能实际上并不想要一个单身人士而是其他东西.一个上下文管理可能是一种可能性.
在某些情况下可以重新实例化的"单身人士",对我来说,实际上是非常奇怪和意想不到的行为,我会反对它.不过,如果这是你真正想要的,你可以self.__class__._instance = None用你的close_()方法做.或者您可以编写一个单独的方法来执行此操作.它看起来丑陋,这是恰当的,因为它是丑陋的.:-)
我认为你的第三个问题也来自这样一个事实,即close_()当你没有编程那种行为时,你希望单身人士在你打电话之后以某种方式消失.
| 归档时间: |
|
| 查看次数: |
1472 次 |
| 最近记录: |