可以是类型或工厂函数的类成员的不同行为
Posted
技术标签:
【中文标题】可以是类型或工厂函数的类成员的不同行为【英文标题】:Different behavior of a class-member which could be a type or a factory-function 【发布时间】:2014-07-26 19:02:15 【问题描述】:每当我定义一个类的实例创建其他类的对象时,我喜欢将那些其他对象的类型定义为类成员:
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
这个想法是允许潜在的子类轻松覆盖它。
我刚刚发现这个习惯有问题,当我使用的“类型”不是真正的类型,而是工厂函数时。例如,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()
【问题讨论】:
什么错误?我没有看到错误...我不明白是什么问题... @JoranBeasley 我添加了有关错误的更多详细信息 我明白了……现在更清楚了…… 【参考方案1】:你可以使用 staticmethod 装饰器来确保你的类不会被传入
>>> class Foo(object):
... DICT_TYPE = staticmethod(my_dict)
...
>>> f = Foo()
>>> f.DICT_TYPE()
【讨论】:
这很聪明,但不优雅。我正在寻找一种适用于类和函数的解决方案。 它应该可以正常工作......它所做的只是不将 self 放入参数中......列表......它比你的类属性优雅得多......因为它仍然通过@987654322 @ ...但我很高兴听到你有它的工作...【参考方案2】:可以使用classproperty
绕过该问题(例如this answer 中定义的):
class Foo(object):
@classproperty
def DICT_TYPE(cls):
return dict_factory
【讨论】:
以上是关于可以是类型或工厂函数的类成员的不同行为的主要内容,如果未能解决你的问题,请参考以下文章
为什么 没有缺省构造函数的类类型成员 必需要在初始化列表 里初始化 ?
为什么 没有缺省构造函数的类类型成员 必需要在初始化列表 里初始化 ?