[英]Assigning Descriptor attribute outside class
我有一個數據存儲延遲加載的描述符,如果數據存儲不可用,則返回默認值。 描述符工作正常,除了我希望默認值是提供的類類型的實例的情況,該類型是與定義描述符相同的類類型(樹層次結構所需)。 理想情況下我想做
from weakref import WeakKeyDictionary
class Descriptor(object):
def __init__(self, classType=None):
self.classType = classType
self.values = WeakKeyDictionary()
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
print("name:", self.name)
if instance not in self.values:
self.values[instance] = self.classType()
return self.values[instance]
def __set__(self, instance, value):
self.values[instance] = value
class Item1(object):
pass
class Item2(object):
parent1 = Descriptor(Item1)
parent2 = Descriptor(Item2)
item2 = Item2()
print(item2.parent1)
print(item2.parent2)
但很明顯,parent2的描述符不能傳遞給它所定義的類。 所以另一種方法是在定義類之后分配parent2:
class Item2(object):
parent1 = Descriptor(Item1)
Item2.parent2 = Descriptor(Item2)
但是,在這種情況下,在創建構造函數時似乎沒有調用__set_name__方法,因為給出了以下錯誤:
name: parent1
<__main__.Item1 object at 0x021F4890>
Traceback (most recent call last):
File "..\setNameTest.py", line 28, in <module>
print(item2.parent2)
File "..\setNameTest.py", line 10, in __get__
print("name:", self.name)
AttributeError: 'Descriptor' object has no attribute 'name'
似乎工作的是在類中創建描述符之后將itemClass值分配給parent2,但在整個代碼庫中使用它似乎很笨重:
class Item2(object):
parent1 = Descriptor(Item1)
parent2 = Descriptor()
Item2.__dict__['parent2'].classType = Item2
有更清潔的方法嗎?
編輯09Mar2017:根據https://stackoverflow.com/a/6995286/1834561 ,如果實例為None,則可以通過從Descriptor返回self來清除此方法.__ get__,即
def __get__(self, instance, owner):
if instance is None:
return self
print("name:", self.name)
if instance not in self.values:
self.values[instance] = self.classType()
return self.values[instance]
現在可以在類定義之外分配classType
Item2.parent2.classType = Item2
因此,當您需要在類級別范圍內訪問類本身時,您必須使用元類 。 但是,我不熟悉新的__set_name__
dunder方法,並且我無法使用它來使用元類。 然而,這是一種替代方式 - 舊方式 - 。 首先,您必須將name
傳遞給您的Descriptor
__init__
:
In [10]: from weakref import WeakKeyDictionary
...:
...: class Descriptor(object):
...: def __init__(self, name, classType=None):
...: self.classType = classType
...: self.values = WeakKeyDictionary()
...: self.name = name
...: def __get__(self, instance, owner):
...: print("name:", self.name)
...: if instance not in self.values:
...: self.values[instance] = self.classType()
...: return self.values[instance]
...: def __set__(self, instance, value):
...: self.values[instance] = value
...:
...:
...: class Item1(object):
...: pass
...:
現在,定義您的元類。 這可能是更好的封裝,但它可以解決這個問題。 再說一遍,請注意,我將name
傳遞給Descriptor
:
In [11]: class ItemMeta(type):
...: def __init__(cls, name, bases, dct):
...: cls.parent1 = Descriptor('parent1', Item1)
...: cls.parent2 = Descriptor('parent2', cls)
...:
...:
最后,使用Python3語法,我們使用元類創建Item2
:
In [12]: class Item2(object, metaclass=ItemMeta):
...: pass
...:
現在,它應該工作:
In [13]: x = Item2()
In [14]: x.parent1
name: parent1
Out[14]: <__main__.Item1 at 0x1104db240>
In [15]: x.parent2
name: parent2
Out[15]: <__main__.Item2 at 0x1104dbc50>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.