Python:类静态成员指向自身?

时间:2011-09-02 11:27:08

标签: python

  

可能重复:
  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和类似的静态变量,并在类声明完成后设置它们的所有者。然而,这似乎是一种令人难以置信的迂回和不直观的方式来做一个非常简单的操作:让一个类的静态/类成员知道他们属于谁。

这样做有“正确”的方法吗?

澄清:

我希望这些成员属于类,而不是实例。我正在尝试使用几乎纯粹功能的样式,仅使用类来继承共享行为,而根本不创建它们的实例。实例将倾向于让我的函数访问所有函数共享的任意实例数据,这将打破我正在尝试的纯函数。我可以使用我不接触的空实例,但我认为使用纯类会更清晰。

3 个答案:

答案 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__方法,以便在询问属性值时返回您想要的任何内容。
  • 您可以使用属性,该属性具有返回您希望它返回的对象的getter。

继承__getattr__个方法和属性。