Функции в словарях в python - PullRequest
0 голосов
/ 27 июня 2018

Я могу хранить функции в словарях, говоря

MyDict = {}

def func():
    print("Hello, world!")

MyDict["func"] = func

Мне было интересно, есть ли более чистый / аккуратный способ написать это - что-то вроде

MyDict = {}

def MyDict["func"]():
    print("Hello, world!")

Однако этот код выдает синтаксическую ошибку

Ответы [ 4 ]

0 голосов
/ 27 июня 2018

Вы можете (ab) использовать декоратор.

MyDict = {}

def store(d, name):
    def _(f):
        d[name] = f
        return f
    return _

@store(MyDict, "func")
def func():
    print("Hello, world!")

@store(MyDict, "foo")
def some_other_func():
    print("Goodbye")

Вы можете упростить это, если вы просто хотите использовать определенное имя в качестве ключа и жестко закодировать словарь для обновления:

def store(f):
    MyDict[f.__name__] = f
    return f

@store
def func():
    print("Hello, world!")
0 голосов
/ 27 июня 2018

Это неправильно:

def MyDict["func"]():
    print("Hello, world!")

потому что после def вам нужно использовать какое-то слово, которое содержит только разрешенных символов . Вот почему вы получили синтаксическую ошибку.

Что вы можете использовать:

1) Лямбда функции (как предложено @bphi)

MyDict = {}
MyDict['func'] = lambda: print("123")
MyDict['func']()

2) Python класс для динамического создания методов (внутри класса), которые хранятся в MyDict, используя setattr встроенную функцию:

def func1():
    print(1)


def func2():
    print(2)


MyDict = {}
MyDict['func1'] = func1
MyDict['func2'] = func2

class MyClass3:
    def __init__(self):
        for name, obj in MyDict.items():
            setattr(self, name, obj)

obj = MyClass3()
obj.func1()
obj.func2()

или через лямбду:

MyDict = {}
MyDict['func1'] = lambda : print(1)
MyDict['func2'] = lambda : print(2)

class MyClass3:
    def __init__(self):
        for name, obj in MyDict.items():
            setattr(self, name, obj)

obj = MyClass3()
obj.func1()
obj.func2()

или

class MyClass3:
    MyDict = {}
    MyDict['func1'] = lambda: print(1)
    MyDict['func2'] = lambda: print(2)

    def __init__(self):
        for name, obj in self.MyDict.items():
            setattr(self, name, obj)

obj = MyClass3()
obj.func1()
obj.func2()
0 голосов
/ 27 июня 2018

Если вы можете выразить все свои функции в виде одной строки, используйте lambda s, как предложено в ответе @ bphi .

Если вы не хотите, чтобы вас ограничивали с помощью лямбда-исчисления, другой способ - использовать класс и его статические методы. Статические методы - это методы класса, а не экземпляра класса, поэтому они не имеют доступа к внутреннему состоянию объекта и могут вызываться для класса, а не для экземпляра.

Однако, прочитав этот ответ, вы можете понять, почему это не очень элегантный (или рекомендуемый) подход, даже если результат именно такой, как вы просили.

class MyClass:
    @staticmethod # this decorator is optional here, but suggested for code clarity
    def func():
        print("Hello, world!")

    def func2():
        print("Hey there, I am another function.")

MyClass.func()
>>> 'Hello, world!'
MyClass.func()
>>> 'Hey there, I am another function.'

Если вы хотите использовать синтаксис словарей, предложенный в вашем вопросе, вы можете использовать __dict__ в классе:

MyDict = dict(MyClass.__dict__)

MyDict["func"]()
>>> 'Hello, world!'
MyDict["func2"]()
>>> 'Hey there, I am another function.'

И вы также можете добавить другие функции в этот словарь:

MyDict["func3"] = lambda: print("Hi, I am yet another function.")

def func4:
    print("And I am the last function for today.")

MyDict["func4"] = func4

MyDict["func"]()
>>> 'Hi, I am yet another function.'
MyDict["func2"]()
>>> 'And I am the last function for today.'

Но так как этот словарь является просто представлением класса MyClass, он также содержит некоторые элементы, связанные с этим классом, например __weakref__. Но вы можете извлечь свои собственные функции:

MyCleanDict = {}
for key, value in MyDict:
    if not key.startswith("_"):
        MyCleanDict[key] = value

Результат - именно то, о чем вы просили, но я сомневаюсь, что сложность подхода стоит результата. Я рекомендую а) использовать lambda -функции, б) придерживаться вашего первого подхода (сначала определить функции, а затем поместить их в dict) или в) переосмыслить реальную проблему, так как вы можете найти другое решение помимо сохранения функций в словарь.

0 голосов
/ 27 июня 2018

Для вашего примера вы можете сделать это:

d = {}
d['func'] = lambda: print('Hello, world!')
d['func']()
>>> 'Hello, world!'

Если вы хотите использовать класс:

class MyClass:
    def func(self):
        print('Hello, world!')

c = MyClass()
c.func()
>>> 'Hello, world!'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...