如何在python namedlist对象上看到属性?

时间:2017-02-24 19:11:52

标签: python inspect

我一直在使用namedlist来创建轻量级类:

from namedlist import namedlist
# create a class
SomeClass = namedlist('SomeClass', 'foo bar', use_slots=False)

# create an object
my_list = SomeClass(1,2)

# set an attribute not specified in the class
my_list.baz = 3

# the attribute is there if I reference it
print(my_list.baz)
# output: 3

有时我想拍摄一个对象,看看是否设置了任何额外的属性:

# this doesn't show 'baz'
import inspect
inspect.getmembers(my_list)

# neither does this
my_list.__dict__

有没有办法可以看到以这种方式添加的任何属性?

2 个答案:

答案 0 :(得分:1)

查看namedlist的来源,我们可以看到工厂函数namedlist()生成类型(示例中为SomeClass)。

现在这很有趣。

一方面,__getattribute____setattribute__没有重载,这使您可以执行my_list.baz = 3之类的操作,然后将其作为my_list.baz进行访问。

另一方面,__dict__property(_asdict)覆盖(在_common_fields()中生成)。这会导致使用__dict__的用户无法看到baz - dir()inspect模块等功能。

虽然在这种情况下我找不到列出添加属性的函数,但如果您知道要查找的属性,仍然可以使用hasattr(my_list, 'baz')检查它是否存在:

>>> from namedlist import namedlist
>>> SomeClass = namedlist('SomeClass', 'foo bar', use_slots=False)
>>> my_list = SomeClass(1,2)
>>> my_list.baz = 3
>>> hasattr(my_list, 'baz')
True

答案 1 :(得分:0)

如果切换类型有问题(可能已经使用了命名列表的旧代码),我发现以下内容使得查看namedlist可以忍受:

def set_attr(self, attr_name, attr_val):
        setattr(self, attr_name, attr_val)
        self.opt_attrs.append(attr_name)

    TypeA = namedlist('TypeA', 'field_a opt_attrs', use_slots=False)
    TypeA.set_attr = set_attr

    TypeB = namedlist('TypeB', 'field_b opt_attrs', use_slots=False)
    TypeB.set_attr = set_attr

    objA = TypeA(1, [])
    objA.set_attr('field_x', 2)

    objB = TypeB(7, [])

objA
# Out: TypeA(field_a=1, opt_attrs=['field_x'])

objA.field_x
# Out: 2

objB
# Out: TypeB(field_b=7, opt_attrs=[])

最好只使用python类。更多的前期代码,更少的事后混淆:

class TypeA:
    def __init__(self, a):
        self.a = a
    def __repr__(self):
        return "A(a={})".format(self.a)

class TypeB:
    def __init__(self, b):
        self.b = b
    def __repr__(self):
        return "B(b={})".format(self.b)

A = TypeA(1)
A.x = 2

B = TypeB(7)

class TypeA:
    def __init__(self, a):
        self.a = a
    def __repr__(self):
        return "A(a={})".format(self.a)

class TypeB:
    def __init__(self, b):
        self.b = b
    def __repr__(self):
        return "B(b={})".format(self.b)

objA = TypeA(1)
objA.x = 2

objB = TypeB(7)

objA
# Out: A(a=1)

objA.__dict__
# Out: {'a': 1, 'x': 2}

objB
# Out: B(b=7)