【发布时间】:2018-02-01 23:38:33
【问题描述】:
我试图了解描述符的工作原理,尤其是与自定义可变类结合使用时。
我的问题的简洁摘要:
- 如何创建一个自定义类,它有描述符,但会是可变的?
现在让我们添加一些上下文和内容。我最近一直在学习 Pluralsights 高级 Python 课程,他们在其中介绍了描述符。因此,我正在使用课程中的模式。但它并没有像我预期的那样工作。
Descriptor的模式:
我使用的是完全不同的,但它具有相同的模式,只是它执行的检查更复杂。但那部分是 单元测试,所以我真的不认为这是一个问题,因为 进一步的理由请继续阅读。
class DataFrameDescriptor:
def __init__(self):
self._instance_data = WeakKeyDictionary()
def __get__(self, instance, owner):
if instance is None:
return self
return self._instance_data[instance]
def __set__(self, instance, value):
# some code which makes sure, the columns of the descriptor
# stay the same
self._instance_data[instance] = value
def __delete__(self, instance):
raise AttributeError("Cannot delete attribute")
描述的自定义类:
这里我再次只放置了类的脚手架,以避免真正的类实现的不必要的大量代码。 基本上,我想要的是有一个自定义类,它实现了一个排序 集合的接口,而集合又由“管理/验证” 描述符。更准确地说,我正在实施 pandas.DataFrame,我对其有某些不变的设置 形状,存储某些对象,我希望我的自定义类是 像字典一样的数据框接口
from collections.abc import MutableMapping
class MutableClass(MutableMapping):
""" All the mutable mapping required methods are implemented and work as intended """
descriptor = DataFrameDescriptor()
def __init__(self, some_dict):
df = prepare(some_dict) # prepares the dict to a dataframe
self.descriptor = df
def __setitem__(self, key, value):
# some checks about the value
self.descriptor.loc[key] = value # value must be specific
现在,我得到的错误的解释:
大多数错误都围绕__hash__ 实现,这是有道理的,因为描述符字典需要键,它们是散列。
但是,据我了解,实现__hash__ 和__eq__,它们具有相同的比较结果,是一种承诺,即对象在其运行时生命周期内不会发生变异(更改)。
就我而言,这绝对不是真的。
我已经实现了__hash__ 和__eq__ 的版本,它们可以正常工作并消除错误。然而,这基本上是一个谎言,因为:
- 我希望能够比较我的对象,比较可以告诉我它们“持有”的信息是否相同
希望我的问题足够详细且易于理解。
一个可能的改写是如何在非散列中使用描述符 自定义类。或者如何制作一个可以与 不可散列的自定义类。
【问题讨论】:
-
对不起,我完全不明白你的问题是什么。您说“大多数错误都围绕着 hash 实现”,但在您的代码中任何地方都没有
__hash__方法。您的MutableClass无法实例化,因为您没有实现所有MutableMapping方法。您正在尝试将字典分配给self.descriptor,它只接受正数。这些都没有任何意义。我认为如果你用一些代码来代替这个冗长的解释,这将有很大的帮助,这些代码可以准确地展示什么是不工作的。 -
是的,我不清楚您的问题到底是什么。您的问题似乎根本与描述符无关,而是与可散列对象有关。
-
@Rawing 是的,我忘了说,所有这些都实现了。我应该更清楚。
-
重点是,我不想实现散列函数,因为这些类的值会在其生命周期内发生变化。我所做的实现工作,但它只是散列了一些类不可更改的值。不完全理想。
标签: python oop dictionary descriptor