Я пытаюсь написать класс Python, который может выполнять следующие действия:
c = MyClass()
a = c.A("a name for A") # Calls internally c.create("A", "a name for A")
b = c.B("a name for B") # Calls internally c.create("B", "a name for B")
A и B могут быть чем угодно (ну, они определены в базе данных, но я не хочу явно определять их в моем коде)
Хакерский обходной путь для этого заключается в следующем:
class MyClass():
def __init__(self):
self.createItem = ""
def create(self, itemType, itemName):
print "Creating item %s with name %s" % (itemType, itemName)
def create_wrapper(self, name):
self.create(self.createItem, name)
def __getattr__(self, attrName):
self.createItem = attrName
return self.create_wrapper
Это будет работать, когда пользователь вызывает что-то вроде:
a = c.A("nameA")
b = c.B("nameB")
Тем не менее, он может упасть в ситуациях, когда указатели функций сохраняются без вызова:
aFunc = c.A
bFunc = c.B
aFunc("nameA") # Is actually calling c.create("B", "nameA"),
# as c.B was the last __getattr__() call
bFunc("nameB")
Какие-нибудь предложения для чего-то, что я пропускаю здесь?
Спасибо
Редактировать: Кажется, я только что понял это, но у Филиппа гораздо более элегантное решение ...
Мое решение было:
class MyClassCreator():
def __init__(self, origClass, itemType):
self.origClass = origClass
self.itemType = itemType
def create_wrapper(self, name):
return self.origClass.create(self.itemType, name)
class MyClass():
def __init__(self):
self.createItem = ""
def create(self, itemType, itemName):
print "Creating item %s with name %s" % (itemType, itemName)
def __getattr__(self, attrName):
return MyClassCreator(self, attrName).create_wrapper
Версия, которую я фактически использовал (поскольку мне требовалось больше сложности, чем один аргумент): (я не знаю, можно ли это сделать с помощью лямбда-функции ...)
def __getattr__(self, attrName):
def find_entity_wrapper(*args, **kwargs):
return self.find_entity(attrName, *args, **kwargs)
return find_entity_wrapper