类成员的不同行为,可以是类型或工厂函数

时间:2014-07-26 19:02:16

标签: python inheritance class-members

每当我定义一个实例创建其他类对象的类时,我喜欢将这些其他对象的类型定义为类成员:

class Foo(object):
    DICT_TYPE = dict  # just a trivial example
    def __init__(self):
        self.mydict = self.DICT_TYPE()

class Bar(Foo):
    DICT_TYPE = OrderedDict  # no need to override __init__ now

这个想法是允许潜在的子类轻易地覆盖它。

我刚刚发现这个habbit有问题,当"类型"我使用的不是真正的类型,而是工厂功能。例如,RLock令人困惑的不是一个类:

def RLock(*args, **kwargs):
    return _RLock(*args, **kwargs)

因此以同样的方式使用它并不好:

class Foo(object):
    LOCK_TYPE = threading.RLock  # alas, RLock() is a function...
    def __init__(self):
        self.lock = self.LOCK_TYPE()

这里的问题是,由于RLock是一个函数,self.LOCK_TYPE绑定到self,导致绑定方法,从而导致错误。


这里有一个快速演示,当使用函数而不是类时出现问题(对于比RLock更简单的情况):

def dict_factory():
    return {}

class Foo(object):
    DICT_TYPE1 = dict
    DICT_TYPE2 = dict_factory

f = Foo()
f.DICT_TYPE1()
=> {}
f.DICT_TYPE2()
=> TypeError: dict_factory() takes no arguments (1 given)

有没有人有解决这个问题的好方法?我对这些班级成员的定义存在根本错误吗?

我想我可以用工厂方法替换它。这会是一个更好的方法吗?

class Foo(object);
    def __init__(self):
        self.lock = self._make_lock()
    def _make_lock(self):
        return threading.RLock()

2 个答案:

答案 0 :(得分:2)

您可以使用staticmethod装饰器来确保您的课程不会被传递

>>> class Foo(object):
...     DICT_TYPE = staticmethod(my_dict)
...
>>> f = Foo()
>>> f.DICT_TYPE()
{}

答案 1 :(得分:0)

使用classproperty(例如this answer中定义的)可以绕过问题:

class Foo(object):
    @classproperty
    def DICT_TYPE(cls):
        return dict_factory