This code:
import inspect
class Obj():
def c(self):
return 1
def b(self):
return 2
def a(self):
return 3
o = Obj()
for name, value in inspect.getmembers(o, inspect.ismethod):
print str(value())+" "+name
print:
3 a
2 b
1 c
Because of inspect.getmembers
return all the members of an object in a list of (name, value) pairs sorted by name, as you can read in https://docs.python.org/2/library/inspect.html#inspect.getmembers
But I want to get that list in the same order that the members was written in the code, in other words, the output would be:
1 c
2 b
3 a
Is any way to do that?
Thanks
Member variables at the top of the class, then constructors, then all other methods. And you order the methods to be close together with how they are used within the class (rather than arbitrarily putting all public then private then protected).
As a rule of thumb, put methods above all methods called from their body. Class methods and static methods: Usually, this is implied by the reading order explained above. Normal methods can call all methods times and thus come first. Class methods can only call class methods and static methods and come next.
No it does not matter at all where in the class the method declaration is placed. When you actually call a method Java will go through the entire class looking for it either way, so the placement is irrelevant.
Abstract—As the order of methods in a Java class has no effect on its semantics, an engineer can choose any order she prefers.
No. Class members are not ordered. They are gathered into a dictionary, immediately losing order. You can resort to tricks like parsing the source, but it will break easily. For starters, the source could not be available.
[edit: it seems python3 allows more flexibility in class creation, making it possible to customize the way class members are gathered, if you are on python3 only, that's probably a better approach]
If changing the code is not a problem, you can use a decorator though:
import inspect
def track_order(fn):
fn.order = track_order.idx
track_order.idx += 1
return fn
track_order.idx = 0
class Obj(object):
@track_order
def c(self):
return 1
@track_order
def b(self):
return 2
@track_order
def a(self):
return 3
o = Obj()
methods = sorted((item
for item in inspect.getmembers(o, inspect.ismethod)),
key=lambda item: item[1].order)
for name, value in methods:
print str(value())+" "+name
The decorator adds an idx
attribute to all methods that pass through it.
This makes use of the fact that python has first-class functions.
$ python test.py
1 c
2 b
3 a
Note: this is the method used by Django to keep track of form and model fields order. Only, they don't need a decorator because fields' classes have the instanciation order attribute built-in (it is named creation_counter
).
When creating an object, all of its attributes are contained in another specialized attribute in the object called __dict__
, which as the name suggests is just a normal Python non-ordered dictionary, hence they are not guaranteed to be stored in the same fashion they were added in. When retrieving the values in __dict__
using getmembers()
, Python automatically reorganizes the dictionary when printing it in order to make some logical sense.
To combat this, something must be done to turn the regular Python dictionary __dict__
into some sort of ordered one.
This can be done a number of ways, for simplicity's sake, I will assume you are using Python 3.
Using the collections
package, you can obtain an OrderedDict
, which is exactly the technology we require for such an issue. Prepare this ordered dictionary for use in a metaclass for the class which needs ordered members to be stored, copy over the members, and finally access this new OrderedDict
when wanting to print out said members.
This can be seen in action in this Stack Overflow answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With