Использование методов класса в цикле for

#python #python-3.x

#python #python-3.x

Вопрос:

У меня есть внешне определенный модуль, в котором есть несколько методов. Я могу получить все методы в виде списка с помощью dir(), например, print(dir[Descriptors]) и я получаю список ['BalabanJ', 'BertzCT',...] . Теперь я хочу применить все методы к списку значений [x1, x2, …]. Если я использую напрямую Descriptors.BalabanJ(x1) , это работает. Однако я хочу выполнять их в цикле, подобном

 from rdkit.Chem import Descriptors
for i in dir[Descriptors]:
    for x in [x1,x2,x3]:
        print(Descriptors.i(x))
  

в нем говорится, что в дескрипторах нет метода i. Как я могу это реализовать?

Комментарии:

1. Существует разница в типах 'BalabanJ' и .BalabanJ() . Первый представляет собой строку, а второй — функцию

Ответ №1:

Я думаю, что getattr это то, что вы ищете

 from rdkit.Chem import Descriptors
for i in dir(Descriptors):
    if callable(i):
        for x in [x1,x2,x3]:
            print(getattr(Descriptors ,i)(x))
  

Комментарии:

1. Спасибо! Не могли бы вы немного объяснить это?

2. Я думаю, что полное объяснение содержится в сообщении BlueSheepToken. функция getattr позволяет получить атрибут объекта по имени (строка). Его можно использовать в модулях, объектах и т.д.

Ответ №2:

Я бы рекомендовал inspect :

 from rdkit.Chem import Descriptors
import inspect

for i in inspect.getmembers(Descriptors, callable):
    for x in [1, 2, 3]:
        print(i[0], i[1](x))  # name of function of Descriptors module, result
  

Комментарии:

1. Это также приведет к сбою, если сигнатуре функции требуется 0 или более 1 аргумента, или тип аргумента недопустим. Итак, я напоминаю о inspect.signature функции.

Ответ №3:

Вы можете получить их с помощью getattr

например

 class Bar:
    def __init__(self, foo):
        self.foo = foo

    def p(self):
        print(self.foo)

bar = Bar('hello word')
getattr(bar, 'p')()
  

Имейте в виду, что если их нет method i , это вызовет ошибку значения, но вы можете установить метод по умолчанию

 getattr(bar, 'pr', lambda :print('no such method: pr'))()
  

Вам нужно определить свой класс и передать его в качестве параметра, как я сделал для bar, если это метод класса

 from rdkit.Chem import Descriptors
for i in dir[Descriptors]:
    for x in [x1,x2,x3]:
        print(getattr(Descriptors, i)(x))
  

вы можете взглянуть на официальную документацию getattr()

Комментарии:

1. Здесь более уместно было бы getattr(bar, 'p')()

2. @mad_ Почему так? (Я имею в виду, почему нет, но почему этот более актуален?) (Я это исправил)

Ответ №4:

Для этого в RDKit есть MolecularDescriptorCalculator .

 from rdkit import Chem
from rdkit.ML.Descriptors import MoleculeDescriptors
from rdkit.Chem import Descriptors

descriptors = [d[0] for d in Descriptors._descList]

smiles = ['CCN','CCNC', 'CCN(C)C']

for d in descriptors[:3]: # just the first three descriptors
    print(d)
    calc = MoleculeDescriptors.MolecularDescriptorCalculator([d])
    for s in smiles:
        c = calc.CalcDescriptors(Chem.MolFromSmiles(s))
        print(s, c[0])
  

Вывод:

 MaxEStateIndex
CCN 4.847222222222222
CCNC 2.9305555555555554
CCN(C)C 2.125
MinEStateIndex
CCN 0.75
CCNC 1.0694444444444444
CCN(C)C 1.1388888888888888
MaxAbsEStateIndex
CCN 4.847222222222222
CCNC 2.9305555555555554
CCN(C)C 2.125
  

Комментарии:

1. О, спасибо! Я специально сохранил ответ на вопрос 🙂