2012-09-18 52 views
3

说我有一个类和函数:把东西放入新的函数属性是不好的做法吗?

class AddressValidator(self): 
    def __init__(self): 
     pass 
    def validate(address): 
     # ... 

def validate_address(addr): 
    validator = AddressValidator() 
    return validator.validate(addr) 

的功能是使用类,如果你愿意的快捷方式。现在,如果这个函数需要运行几千次呢?如果验证器类实际上需要做一些实例化操作,比如连接到数据库,那么创建它数千次是非常浪费的。我在想,如果我也许可以做这样的事情:

def validate_address(addr): 
    if not hasattr(validate_address, 'validator'): 
     validate_address.validator = AddressValidator() 

    validator = validate_address.validator 
    return validator.validate(addr) 

现在Validator类是只实例化一次和“功能”保存,把这种方式。我从来没有见过这样做,所以我猜这是不好的做法。如果是这样,为什么?

注意:我知道我可以将验证器对象缓存在全局模块中。我只是好奇,如果这是一个可行的解决方案,当我想避免乱抛我的模块。

+0

这不是一个不好的做法。毕竟,函数是对象。这只是为您的问题提供更好的解决方案。就像你说的那样:将'AddressValidator'存储在全局范围内。或者创建一个单身人士。或者将它作为参数传递。这取决于你的实际使用。 – freakish

+0

哪里是添加一个函数和有一个实例arround你用它的区别?两个都取一个名字。请参阅Odomontois答案,以获得更好的解决方案 – ted

回答

3

尽管“长生不老”是一个对象,但并不像一个控制良好的阶级一样好。 这个问题看起来像在python中调用的“functor”或“callable object”的典型情况。

的代码会看起来像

class AddressValidator(self): 
    def __init__(self): 
     pass 
    def __call__(self,address): 
     # ... 

validate_address = AdressValidator() 

,或者你可以只定义功能快捷键绑定的方法

class AddressValidator(self): 
    def __init__(self): 
     pass 
    def validate(self,address): 
     # ... 

validate_adress = AdressValidator().validate 
+1

您需要在第二个示例中的验证定义之上的@staticmethod。 – Jake

+0

@Jake谢谢。我错过了。但是,添加自引用而不是staticmethod装饰器似乎更好,因为作者想要使用某些实例属性,并且方法已被称为* bound * – Odomontois

+0

这仍然是每次都实例化类;与Codemonkey的解决方案一样,只有更少的代码行。 – Hossein

3

我会用默认参数。(在函数定义时计算一次,并绑定功能):

def validate_address(addr, validator=AddressValidator()) 
    return validator.validate(addr) 

这是完全可以接受的,如果的AddressValidator情况下,被认为是不可变的(即他们不” t包含修改其内部状态的方法),并且如果您发现需要(例如提供专门针对特定国家/地区的验证器),您还可以稍后重写验证器的选择。

+0

理论上这是一个很好的解决方案,但AddressValidator构造函数使用了很多模块的功能,当定义了“validate_address”时,它没有准备好,这意味着我必须将定义在文件的底部。 – Hubro

+0

这样做有什么问题吗?看起来好像基本上是一个'AddressValidator.validate'的简单封装器(注意这个包装器通常不被认为是Pythonic ...) – nneonneo

+0

这不是问题,它只是令人烦恼。我有我的课程和功能分组和组织的方式是有道理的,不得不把我的一个功能拉出美丽的模式,并把它放在文件的底部给我OCD痉挛。我最终删除了包装并使用@odomontois的解决方案。 – Hubro

相关问题