Вызов нескольких функций из класса в 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, параметры упаковки.

Другие вопросы по тегам