使用Python反射获取字段名称
在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
...