Getting field names reflectively with Python
Is it possible to get the name of a field reflectively in Python (3.2)?
See the following example:
class Something:
def __init__(self):
self.x = 1
def validate():
return validator.max(self.x, 10)
validator.max(self.x, 10)
should produce an error message containing the name of the field x
as string (in this开发者_开发技巧 case "x"
).
You would have to pass the attribute name as a string
def validate():
return validator.max(self, "x", 10)
then validator.max might look like this
def max(ob, attr, max_value):
val = getattr(ob, attr) # val would be self.x now
...
Unlikely. Things might not even have names - what is:
validator.max(3,10)
supposed to do?
Pass the name as well as the value if you want it output:
validator.max(self.x,10,"x")
whatever validator.max is, it needs another argument, or if its a builtin, you need to wrap it.
In Python the expression self.x
is just the current value of that member and the information that the value is coming from an object is therefore lost.
However you can move the validation logic at an higher level (base class) and having it working on a whole object. With this approach validator "name" will be known by the validate function and can be used for the error message:
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)
Note of course that disabling a check in a derived class is illogical from an IS-A point of view, here is just as an example showing that dir
will correctly find inherited members.
精彩评论