使用Python反射获取字段名称

3 投票
3 回答
10171 浏览
提问于 2025-04-16 16:34

在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 个回答

2

不太可能。事情可能连名字都没有——这是什么:

validator.max(3,10)

应该做什么呢?

如果你想要输出结果,就需要同时传入名字和数值:

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

无论validator.max是什么,它都需要另一个参数,或者如果它是内置的,你需要把它包裹起来。

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)

当然需要注意的是,从“是一个”的角度来看,在派生类中禁用某个检查是没有逻辑的,这里只是作为一个例子,展示了dir能够正确找到继承的成员。

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
    ...

撰写回答