Вызов нескольких функций из класса в Python без повторения имени класса каждый раз
Я чувствую, что это очень простой вопрос, но я не могу найти правильный ответ. В основном у меня есть список вызовов функций из класса с именем имитация:
simulation.addGroup("teapotarmy")
simulation.populateGroup(20)
simulation.addNode("input",INPUT)
simulation.addNode("output",OUTPUT);
simulation.connectNodes("input","output");
simulation.manipOutputNode("output", "group.xvel");
simulation.manipInputNode("input", 1, 0.05);
Есть ли способ вызвать эти функции без необходимости повторять имя класса каждый раз? Что-то по линии:
(thethingIwant) simulation:
addGroup("teapotarmy")
populateGroup(20)
addNode("input",INPUT)
...
Я сделал это на других языках программирования, но я не понял синтаксис в Python. У меня слабое воспоминание о том, что это как-то связано с выражением "с"...? Заранее спасибо.
Леон
3 ответа
Просто нет. Нет (хорошо, см. Мой комментарий в конце) способ сделать это. Лучшее, что вы можете сделать, это присвоить его другому, более короткому имени:
s = simulation
s.addGroup("teapotarmy")
...
Что не так уж и плохо, хотя я бы сказал, что обычный метод является более читабельным.
В качестве дополнения, это не совсем верно, что вы не можете сделать это. Вы можете назначить все методы моделирования локальному пространству имен программно, однако, это будет довольно запутанным, и я бы посоветовал против этого.
Пример:
from contextlib import contextmanager
import inspect
class some_class:
def test(self):
print("test!")
@contextmanager
def map_to_local(inst, locals):
methods = inspect.getmembers(inst, inspect.ismethod)
for name, method in methods:
locals[name] = method
yield
for name, method in methods:
del locals[name]
inst = some_class()
with map_to_local(inst, locals()):
test()
Обратите внимание, что это довольно хрупко - вам нужно быть осторожным и делать такие вещи, как проверка того, что вы не перезаписываете значения, проверка значений не была удалена до выхода из диспетчера контекста и т. Д. Это также довольно неясно.
tl; dr: Да, это возможно, нет, вы не должны этого делать. Ваш текущий код в порядке и понятен.
Для работы с существующим классом в том виде, в котором он создан в настоящее время, обычным решением является использование более короткого имени переменной:
s = simulation
s.addGroup("teapotarmy")
s.populateGroup(20)
s.addNode("input",INPUT)
s.addNode("output",OUTPUT)
s.connectNodes("input","output")
s.manipOutputNode("output", "group.xvel")
s.manipInputNode("input", 1, 0.05)
Тем не менее, альтернативное решение состоит в том, чтобы немного изменить класс, чтобы эти методы возвращали себя. Тогда вы можете написать:
(simulation
.addGroup("teapotarmy")
.populateGroup(20)
.addNode("input",INPUT)
.addNode("output",OUTPUT)
.connectNodes("input","output")
.manipOutputNode("output", "group.xvel")
.manipInputNode("input", 1, 0.05))
Обычный стиль Python состоит в том, чтобы мутирующие методы возвращали None (чтобы намекнуть, что произошла мутация); однако возвращение self является нормой для таких API, как ваш, где принято применять последовательность преобразований и обновлений состояний.
Для каждого метода, который вы определяете в своем классе, вы можете вернуть объект self.
class schema:
def __init__(self,name,age):
self.name = name
self.age = age
def giveName(self):
print(self.name)
return self
def giveAge(self):
print(self.age)
return self
obj = schema(name="yo",age=15)
obj.giveName().giveAge()
Самое близкое, что я могу придумать, - это воспользоваться тем фактом, что функции Python также являются атрибутами вашего класса (вызываемые атрибуты), и поэтому вы можете "получить" их по имени и вызвать их...
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class Simulation(object):
def addGroup(self, groupToAdd):
print "Group to add: %s" % groupToAdd
def addNode(self, inputType, inputChannel):
print "My inputs: %s, channel: %s" % (inputType, inputChannel)
if __name__ == "__main__":
simulation = Simulation()
functionsToCall = [
("addGroup", "teapotarmy"),
("addNode", "input", "INPUT"),
]
for functionToCall in functionsToCall:
getattr(simulation, functionToCall[0])(* functionToCall[1:])
Но это, вероятно, делает ваш код более запутанным, чем раньше. Если кто-то должен изменить ваш код, это может усложнить его задачу... совсем немного. :)
Для получения дополнительной информации: Callables, параметры упаковки.