可能重复:
Can I get a reference to the 'owner' class during the init method of a descriptor?
代码胜过千言万语:
>>> class ShortRib(object):
>>> def __init__(self, owner):
>>> self.owner = owner
>>>
>>> ... some more methods and stuff ...
>>>
>>>
>>> class Cow(object):
>>> shortRib = ShortRib(self)
>>>
>>>
>>> class BrownCow(Cow):
>>> pass
>>>
>>> BrownCow.shortRib.owner
<class '__main__.BrownCow'>
这不起作用,但我希望如此。基本上,我希望每个类都有一些静态/类变量(我不确定它在这种情况下是什么?)但需要每个人知道它属于谁(哪个类)。不幸的是,我无法“获得”类声明正文中的类。当然,我总是可以使用装饰器来做到这一点:
>>> def vars(**kwargs):
>>> def wrap(cls):
>>> for k, w in kwargs.items():
>>> setattr(cls, k, w(cls))
>>> return cls
>>> return wrap
>>>
>>> @vars(shortRib=lambda cls: ShortRib(cls)
>>> class BrownCow(Cow):
>>> ...
>>>
>>> BrownCow.shortRib.owner
哪个会奏效。另一种方法是让类装饰器遍历所有shortRib和类似的静态变量,并在类声明完成后设置它们的所有者。然而,这似乎是一种令人难以置信的迂回和不直观的方式来做一个非常简单的操作:让一个类的静态/类成员知道他们属于谁。
这样做有“正确”的方法吗?
澄清:
我希望这些成员属于类,而不是实例。我正在尝试使用几乎纯粹功能的样式,仅使用类来继承共享行为,而根本不创建它们的实例。实例将倾向于让我的函数访问所有函数共享的任意实例数据,这将打破我正在尝试的纯函数。我可以使用我不接触的空实例,但我认为使用纯类会更清晰。
答案 0 :(得分:2)
您可以在__new__
:
class ShortRib(object):
def __init__(self, owner):
self.owner = owner
class Cow(object):
shortRib = None
def __new__(cls, *args, **kwargs):
if cls.shortRib == None:
cls.shortRib = ShortRib(cls)
return super(Cow, cls).__new__(cls, *args, **kwargs)
Cow()
Cow.shortRib.owner
甚至__init__
,如果您不介意引用self.__class___
。
您也可以使用元类来完成:
class ShortRib(object):
def __init__(self, owner):
self.owner = owner
class MetaCow(type):
def __new__(cls, name, base, attrs):
attrs['shortRib'] = ShortRib(cls)
return super(MetaCow, cls).__new__(cls, name, base, attrs)
class Cow(object):
__metaclass__ = MetaCow
Cow.shortRib.owner
答案 1 :(得分:1)
为什么不让Cow类的实例使用shortRib而不是类本身?:
class ShortRib(object):
def __init__(self,owner):
self.owner=owner
class Cow(object):
def __init__(self):
self.shortRib=ShortRib(self)
class BrownCow(Cow):
pass
print(BrownCow().shortRib.owner)
# <__main__.BrownCow object at 0xb76a8d6c>
(否则,你需要一个类装饰器或元类 - 就像你已经提到的那样。但是简单比复杂更好,所以为什么不选择简单?)
顺便说一下,如果你确实想要使用类而不是实例:
class ShortRib(object):
def __init__(self, owner):
self.owner = owner
class MetaCow(type):
def __init__(cls, name, base, attrs):
super(MetaCow, cls).__init__(name, base, attrs)
cls.shortRib = ShortRib(cls)
class Cow(object):
__metaclass__ = MetaCow
class BrownCow(Cow):
pass
print(Cow.shortRib.owner)
# <class '__main__.Cow'>
print(BrownCow.shortRib.owner)
# <class '__main__.BrownCow'>
使用
class MetaCow(type):
def __new__(cls, name, base, attrs):
不正确。 type.__new__
的签名是
class MetaCow(type):
def __new__(meta, name, base, attrs):
由于您要修改cls
而不是meta
的属性,请使用MetaCow.__init__
而不是MetaCow__new__
。
答案 2 :(得分:0)
两种方法可以做你想做的事:
__getattr__
方法,以便在询问属性值时返回您想要的任何内容。继承__getattr__
个方法和属性。