inspect.getmembers(object[, predicate])
Возвратите всех членов объекта в списке (имя, значение) пары, отсортированные по имени.
Я хочу использовать этот метод, но я не хочу, чтобы участники были отсортированы. Я хочу их, возвратился в том же порядке, они были определены. Существует ли альтернатива этому методу?
Вариант использования:
Создание формы как так:
class RegisterForm(Form):
username = Field(model_field='username', filters=validators.minlength(3))
password1 = Field(model_field='password', widget=widgets.PasswordInput)
password2 = Field(widget=widgets.PasswordInput)
first_name = Field(model_field='first_name')
last_name = Field(model_field='last_name')
address = SubForm(form=AddressForm, model_field='address')
Я хочу, чтобы поля были представлены в том же порядке, они определяются.
Вы можете покопаться, чтобы найти номер строки для методов, не уверен насчет других членов:
import inspect
class A:
def one(self):
pass
def two(self):
pass
def three(self):
pass
def four(self):
pass
def linenumber_of_member(m):
try:
return m[1].im_func.func_code.co_firstlineno
except AttributeError:
return -1
a = A()
l = inspect.getmembers(a)
print l
l.sort(key=linenumber_of_member)
print l
печатает:
[('__doc__', None), ('__module__', '__main__'), ('four', <bound method A.four of <__main__.A instance at 0x0179F738>>), ('one', <bound method A.one of <__main__.A instance at 0x0179F738>>), ('three', <bound method A.three of <__main__.A instance at 0x0179F738>>), ('two', <bound method A.two of <__main__.A instance at 0x0179F738>>)]
[('__doc__', None), ('__module__', '__main__'), ('one', <bound method A.one of <__main__.A instance at 0x0179F738>>), ('two', <bound method A.two of <__main__.A instance at 0x0179F738>>), ('three', <bound method A.three of <__main__.A instance at 0x0179F738>>), ('four', <bound method A.four of <__main__.A instance at 0x0179F738>>)]
Я не думаю, что в Python 2.6 есть метод __ prepare __
, поэтому я не могу заменить стандартный dict
на заказной. Однако я могу заменить его, используя метакласс
и метод __ new __
. Вместо проверки номеров строк, я думаю , что проще и эффективнее просто использовать счетчик создания.
class MetaForm(type):
def __new__(cls, name, bases, attrs):
attrs['fields'] = OrderedDict(
sorted(
[(name, attrs.pop(name)) for name, field in attrs.items() if isinstance(field, Field)],
key=lambda t: t[1].counter
)
)
return type.__new__(cls, name, bases, attrs)
class Form(object):
__metaclass__ = MetaForm
class Field(object):
counter = 0
def __init__(self):
self.counter = Field.counter
Field.counter += 1
Атрибуты (методы и другие члены) объекта обычно ищутся с помощью специального атрибута объекта __ dict __
, который является стандартным словарем Python. Это не гарантирует какой-либо конкретный заказ.
Если атрибут не найден в __ dict __
объекта, вместо него выполняется поиск класса (там, где обычно находятся методы) и так далее, пока не будет пройдена вся цепочка наследования.
Вот некоторая пользовательская проверка, выполненная в интерактивном приглашении, чтобы проиллюстрировать это (Python 3.1):
>>> class Klass():
... def test(self):
... pass
...
>>> k = Klass()
>>> k.__dict__
{}
>>> k.__class__.__dict__.items()
[('test', <function test at 0x00000000024113C8>), ('__dict__', <attribute '__dic
t__' of 'Klass' objects>), ('__module__', '__main__'), ('__weakref__', <attribut
e '__weakref__' of 'Klass' objects>), ('__doc__', None)]
Я бы поместил конструктор ( __ init __
) в Klass и установил атрибут через self
это могло бы появиться в k .__ dict __
.
Вы можете обойти это, используя собственный метакласс. В документации есть пример, который делает именно то, что вы хотите.
См. Внизу этой страницы пример OrderedClass .
Не знаю, какая у вас версия Python, поэтому я предположил, что это последняя версия.