使用Python反射获取字段名称

3

在 Python (3.2) 中,是否可以通过反射机制获取字段名称?

请看以下示例:

class Something:
    def __init__(self):
        self.x = 1

    def validate():
        return validator.max(self.x, 10)

validator.max(self.x, 10) 应该产生一个包含字段名 x 的错误信息(在这种情况下为 "x")的字符串。

3个回答

5
您需要将属性名称作为字符串传递。
def validate():
    return validator.max(self, "x", 10)

那么 validator.max 可能是这样的。
def max(ob, attr, max_value):
    val = getattr(ob, attr)    # val would be self.x now
    ...

2
不太可能。事物甚至可能没有名称 - 例如:
validator.max(3,10)

应该做什么?

如果想要输出名称和值,需要同时传递名称和值:

validator.max(self.x,10,"x")

无论 validator.max 是什么,它都需要另一个参数,或者如果它是内置函数,则需要进行包装。

1
此外,函数参数在调用函数之前被求值。 - user395760
self.xx 有点冗余。 - Noufal Ibrahim

2
在Python中,表达式self.x只是该成员的当前值,因此丢失了该值来自对象的信息。
但是,您可以将验证逻辑移到更高级别(基类),并使其在整个对象上工作。采用这种方法,验证器“名称”将被验证函数知道,并可用于错误消息:
class ValidatedObject:
    def validate(self):
        for name in dir(self):
            if (name.startswith("validate_") and  # Is a validator
                not getattr(self, name)()):       # and failed
                raise RuntimeError("%s: %s" %
                                   (name, getattr(self, name).__doc__))

class Something(ValidatedObject):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def validate_x(self):
        "Horizontal position shouldn't be that big"
        return self.x < 10

    def validate_y(self):
        "Vertical position must be neither too low nor too high"
        return 20 <= self.y <= 30

    def validate_sum(self):
        "The position must be on the prescribed line"
        return self.x + self.y == 25

class Something2(Something):
    def validate_sum(self):
        return True

Something(3, 22).validate()   # Ok
Something2(5, 30).validate()  # Ok (derived class relaxed checks)
print "About to crash...."
Something2(5, 31).validate()  # Not ok (Y is too high - inherited check)

当然,从IS-A的角度来看,在派生类中禁用检查是不合逻辑的。这里只是一个例子,说明dir将正确地找到继承的成员。请注意,保留HTML标记。

就此而言,validate() 可以被修改以在构建错误消息时提取和使用方法名中 "validate_" 后面的文本。DRY。 - martineau
@martineau:使用__doc__并不是重复,它可以是一个与验证器名称无关的用户友好信息。在:之前的消息中已经使用了验证器的名称(但不会删除“validate_”)。我将添加一个编辑以使意图更加清晰... - 6502
我对使用__doc__字符串没有问题 - 只是提出了一个建议,使其更符合OP问题中所述的“获取字段名称”的要求。你想出来的东西不仅可以进行简单的字段值验证(在我看来这是一件好事)。 - martineau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接