如何知道哪些属性和对象具有指定的值

2024-09-30 14:21:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我是python的新手,非常感谢您对我的问题的帮助。你知道吗

我有一个类a和三个子类B,C,D,它们都是从a继承的,就像这样。你知道吗

class A:
    def __init__(self, arg1, arg2, arg3):
        self.attr1 = B
        self.attr2 = C
        self.attr3 = D

class B(A):
    name = name
    other = other

class C(A):
    name = name
    other = other

class D(A):
    name = name
    other = other

我想写一个全局方法,其含义如下: “如果输入属性不等于指定对象中列出的任何属性,则从对象B、C、D中获取输入属性。”。我想我可以实现这样的代码。你知道吗

def GlobalMethod(self, input):
    if input != self.__dict__:
        getattr(A, name=input)                         
        print('attribute found here:'+getattr(self.name))
    else:
        print('attribute not found')

将实例分配给子类之后

b = B()
c = C()
d = D()

我最终会像这样传递值(为了示例,我只编写一个实例)

GlobalMethod(b, 'big bang')

主要问题:

  1. 当ErrorType返回时,getattr()不接受关键字arg。

  2. 我不知道如何实现“任何属性”。我认为口述可能是个好方法。

  3. 我不知道如何实现“从对象B,C,D拥有的任何对象”

提前感谢您的帮助!(如果我的描述和代码比较混乱,我很抱歉)


Tags: 对象方法代码nameselfinput属性def
1条回答
网友
1楼 · 发布于 2024-09-30 14:21:29

如果要在A的实例中查找属性值,只需将所有属性值放在一个池中并扫描它即可获取匹配的对象。你知道吗

所以:

class MappingPool:
    def __init__(self):
        self.pool = []
    def add_scannable_object(self, obj):
        self.pool.append(obj)
    def search(self, some_value):
        for obj in self.pool:
            for attr in obj.__dict__:
                if getattr(obj, attr) == some_value:
                    return obj

应返回找到的第一个对象,该对象包含与所需值匹配的属性。我将搜索限制为实例属性,而不包括类属性,因为您似乎只对这些属性感兴趣。(在A.__init__中定义的那些。)

要使用它:

mapping = MappingPool()
b = B('a','b','c')
c = C('test','d','e')
d = D('f','g','h')
mapping.add_scannable_object(b)
mapping.add_scannable_object(c)
mapping.add_scannable_object(d)
x = mapping.search('test') # x is now an alias to c

更新以对注释作出反应,并澄清属性和类属性之间的关系

对放入映射池的对象没有限制。不管它值多少钱,你可以把任何有__dict__属性的东西放进去。任何类和任何类的任何实例都是合适的。也就是说,如果除了您定义的ABCD类之外:

class Test:
    where_is_it = 5
    def __init__(self):
        it_is_here = 9

然后,可以将Test的任何实例添加到用于放置bcd的相同MappingPool中,如上图所示。因此:

mapping = MappingPool()
b = B('a','b','c')
c = C('test','d','e')
d = D('f','g','h')
test = Test()
mapping.add_scannable_object(b)
mapping.add_scannable_object(c)
mapping.add_scannable_object(d)
mapping.add_scannable_object(test)
x = mapping.search(9)
print(x is test) # prints True

当我说搜索不包括类属性时,我想警告的是,使用上面的设置,mapping.search(5)返回None,即使test.where_is_it5。你知道吗

这是因为实例变量和类变量是在两个不同的名称空间中定义的,并且使用obj.__dict__只返回实例的名称空间。你知道吗

您可以通过键入test.__dict__来说服自己,它返回{'it_is_here': 9}。那么where_is_it属性去了哪里?在类命名空间中,因为它是在类级别定义的:

>>> test.__class__.__dict__
mappingproxy({'__dict__': <attribute '__dict__' of 'Test' objects>, '__weakref__': <attribute '__weakref__' of 'Test' objects>, '__doc__': None, '__init__': <function Test.__init__ at 0x7f4bf6f09d08>, '__module__': '__main__', 'where_is_it': 5})

因此,如果需要同时考虑正在扫描的对象的实例属性和类属性,则需要将两者结合起来:

from itertools import chain

for attr in chain(test.__dict__, test.__class__.__dict__):
    print(attr)

输出:

it_is_here
__dict__
__weakref__
__doc__
__init__
__module__
where_is_it

结论,如果您想在实例属性之上支持类属性,只需将for attr in obj.__dict__:替换为for attr in chain(obj.__dict__, obj.__class__.__dict__):。你知道吗

相关问题 更多 >