Это хороший подход для выполнения списка операций над структурой данных в Python? - PullRequest
3 голосов
/ 01 мая 2010

У меня есть словарь данных, ключ - имя файла, а значение - другой словарь значений его атрибутов. Теперь я хотел бы передать эту структуру данных различным функциям, каждая из которых выполняет некоторый тест для атрибута и возвращает True / False.

Один из подходов состоит в том, чтобы вызывать каждую функцию одну за другой из основного кода. Однако я могу сделать что-то вроде этого:

#MYmodule.py
class Mymodule:
  def MYfunc1(self):
  ...
  def MYfunc2(self):
  ...

#main.py
import Mymodule
...
#fill the data structure
...
#Now call all the functions in Mymodule one by one
for funcs in dir(Mymodule):
   if funcs[:2]=='MY':
      result=Mymodule.__dict__.get(funcs)(dataStructure)

Преимущество этого подхода состоит в том, что реализация основного класса не должна изменяться, когда я добавляю больше логики / тестов в MYmodule.

Это хороший способ решить проблему под рукой? Есть ли лучшие альтернативы этому решению?

Ответы [ 2 ]

6 голосов
/ 01 мая 2010

Я бы сказал, что лучший и гораздо более питонский подход - определить декоратор , чтобы указать, какие функции вы хотите использовать:

class MyFunc(object):
    funcs = []
    def __init__(self, func):
        self.funcs.append(func)

@MyFunc
def foo():
    return 5

@MyFunc
def bar():
    return 10

def quux():
    # Not decorated, so will not be in MyFunc
    return 20

for func in MyFunc.funcs:
    print func()

Выход:

5
10

По сути, вы выполняете ту же логику: берете только те функции, которые были определены определенным образом, и применяете их к определенному набору данных.

1 голос
/ 01 мая 2010

Шридхар, предложенный вами метод очень похож на тот, который используется в модуле unittest.

Например, вот как unittest.TestLoader находит имена всех методов тестирования, которые нужно запустить (поднято из /usr/lib/python2.6/unittest.py):

def getTestCaseNames(self, testCaseClass):
    """Return a sorted sequence of method names found within testCaseClass
    """
    def isTestMethod(attrname, testCaseClass=testCaseClass, prefix=self.testMethodPrefix):
        return attrname.startswith(prefix) and hasattr(getattr(testCaseClass, attrname), '__call__')
    testFnNames = filter(isTestMethod, dir(testCaseClass))
    if self.sortTestMethodsUsing:
        testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing))
    return testFnNames

Как и ваше предложение, unittest использует dir для отображения всех атрибутов testCaseClass, и фильтрует список тех, чье имя начинается с prefix (в другом месте оно равно 'test').

Я предлагаю несколько незначительных изменений:

Если вы поместите функции в MYmodule.py, тогда (конечно) оператор импорта должен быть

import MYmodule

Используйте getattr вместо .__dict__.get. Он не только короче, но и продолжает работать, если вы подкласс Mymodule. Возможно, в данный момент это не является вашим намерением, но, в любом случае, использование getattr, вероятно, является хорошей привычкой по умолчанию.

for funcs in dir(MYmodule.Mymodule):
   if funcs.startswith('MY'):
      result=getattr(MYmodule.Mymodule,funcs)(dataStructure)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...