如何有条件地运行@property getter,例如用于过滤目的

问题描述 投票:0回答:1

我有一个类的属性的字典列表,它使用@property getter和setter实现。然而,我希望有一个条件getter或具有相同名称的替代实现。

我的班级和@property有getter和setter运行和单元测试。唯一缺少的是用于过滤目的的pythonic实现条件getter。

我查看了官方文档,谷歌搜索,非常简要地看了一些Pandas源代码。

# python v3.7.2
# simplified code

class MyClass:
    def __init__(self)
    self.uuid = str(uuid.uuid4())
    self.my_dict = []

@property
def mydict(self)
    return self._mydict

@mydict.setter
def mydict(self, inputdict)
    self._mydict.append({
        'target': inputdict.get('target').uuid})

A,B,C = MyClass()

A.mydict = {'target':B}

打印(A.mydict)

[{'target':B.uuid}]

A.mydict = {'target':C}

打印(A.mydict)

[{'target':B.uuid},{'target':C.uuid}]

而且我希望拥有

打印(A.mydict(目标= B))

[{'target':B.uuid}]

这需要额外的编码来处理getter中的假设关键字参数

TypeError:'list'对象不可调用

python decorator
1个回答
0
投票

正如评论员所建议的,并且由于属性和方法之间的故意差异,并且由于我正在处理的事情具有数据和行为,我为此创建了一个专门的类。

我发布了行为的类和单元测试。最有可能的是,这段代码很容易出错,但它可以完成当前版本的宠物项目。欢迎任何有关可用性和扩展的提示和潜在问题。

class Correspondence(dict):
"""A class for Correspondence data structure, see Chapter 2 of the book."""

def update(self, *args, **kwargs):
    """Update the correspondence object with the unique keys."""
    try:
        keyid = args[0]['target'] + args[0]['source'] + args[0]['condition']
        self[keyid] = args[0]
    except KeyError:
        raise TypeError('The input should contain source, target, \
            condition and truthvalue as keys of the input dictionary')

def filter(self, source=None, target=None, condition=None, truthvalue=None):
    """Filter Correspondence object. (target ⇐ source))

    Input:
        source:     filtering condition, source
        target:     filtering condition, target
        condition:  filtering conidtion, correspondence condition
        truthvalue: filtering condition, truthvalue excluding 
    Output:
        output: a Correspondence instance
    """

    filters = {
        'source': source,
        'target': target,
        'condition': condition,
        'truthvalue': truthvalue}
    filters = {k: v for k, v in filters.items() if v is not None}


    if not bool(filters):
        return self
    else:
        _correspondence = copy.deepcopy(self)
        # iterate over filters, followed by iteration over items
        # if the conditions are not satisfied, then items are removed
        # matrix-based computation would be more efficient,
        # but would do for now unless performance issues
        for filter_key, filter_value in filters.items():
            for key, value in self.items():
                if value[filter_key] is not filter_value:
                    del _correspondence[key]

        return _correspondence

单元测试

def test_correspondence_structure_and_methods(self):
    # check if correspondence has the right structure
    BA_correspondence = {
        'source': 'A.uuid',
        'target': 'B.uuid',
        'condition': 'the condition',
        'truthvalue': 'true'}

    CA_correspondence = {
        'source': 'A.uuid',
        'target': 'C.uuid',
        'condition': 'the condition',
        'truthvalue': 'true'}

    CA_correspondence_wrong = {
        'sources': 'A.uuid',          # the key should be "source"
        'target': 'C.uuid',
        'condition': 'the condition',
        'truthvalue': 'true'}

    BA_correspondence_upd = {
        'source': 'A.uuid',
        'target': 'B.uuid',
        'condition': 'the condition',
        'truthvalue': 'unverifiable'}

    correspondence = fabric.Correspondence()

    # test if Correspondence.update() processes the right data
    self.assertRaises(
        TypeError,
        correspondence.update,
        CA_correspondence_wrong)

    correspondence.update(BA_correspondence)
    # (B ⇐ A)
    self.assertDictEqual(
        {'B.uuidA.uuidthe condition': BA_correspondence},
        correspondence)

    # (B ⇐ A) ⋅ (C ⇐ A)
    correspondence.update(CA_correspondence)
    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence)

    # updated truthvalue with the same source, target, and condition
    # (B ⇐ A) ⋅ (C ⇐ A)
    correspondence.update(BA_correspondence_upd)
    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence)

    # filter correspondence
    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence.filter())

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd},
        correspondence.filter(target='B.uuid'))

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence.filter(source='A.uuid'))

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd,
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence.filter(condition='the condition'))

    self.assertDictEqual(
        {
            'C.uuidA.uuidthe condition': CA_correspondence},
        correspondence.filter(truthvalue='true'))

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd},
        correspondence.filter(source='A.uuid', truthvalue='unverifiable'))

    self.assertDictEqual(
        {
            'B.uuidA.uuidthe condition': BA_correspondence_upd},
        correspondence.
            filter(source='A.uuid').filter(truthvalue='unverifiable'))
© www.soinside.com 2019 - 2024. All rights reserved.